diff --git a/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java b/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java index 89b14779ccc..bb68e53939b 100644 --- a/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java +++ b/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java @@ -33,8 +33,6 @@ import com.cloud.cluster.ClusterInvalidSessionException; import com.cloud.cluster.ManagementServerHost; import com.cloud.cluster.ManagementServerHost.State; import com.cloud.cluster.ManagementServerHostVO; -import com.cloud.host.HostVO; -import com.cloud.host.Status; import com.cloud.utils.DateUtil; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; @@ -92,9 +90,10 @@ public class ManagementServerHostDaoImpl extends GenericDaoBase l = listIncludingRemovedBy(sc); - if(l != null && l.size() > 0) - return l.get(0); + if(l != null && l.size() > 0) { + return l.get(0); + } return null; } @@ -232,8 +232,9 @@ public class ManagementServerHostDaoImpl extends GenericDaoBase implements Gene } @Override - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") @DB(txn=false) public GenericSearchBuilder createSearchBuilder(Class resultType) { final T entity = (T)_searchEnhancer.create(); final Factory factory = (Factory)entity; diff --git a/utils/src/com/cloud/utils/db/Transaction.java b/utils/src/com/cloud/utils/db/Transaction.java index 4e60c059f23..c54ad013ad2 100755 --- a/utils/src/com/cloud/utils/db/Transaction.java +++ b/utils/src/com/cloud/utils/db/Transaction.java @@ -27,6 +27,7 @@ import java.sql.Savepoint; import java.sql.Statement; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Properties; import javax.sql.DataSource; @@ -43,6 +44,7 @@ import org.apache.log4j.Logger; import com.cloud.utils.Pair; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.mgmt.JmxUtil; /** * Transaction abstracts away the Connection object in JDBC. It allows the @@ -119,6 +121,12 @@ public class Transaction { tls.set(txn); txn.takeOver(name, true); + try { + s_logger.debug("Registering txn" + System.identityHashCode(txn)); + JmxUtil.registerMBean("Transaction", "txn" + System.identityHashCode(txn), new TransactionMBeanImpl(txn)); + } catch (Exception e) { + s_logger.error("Unable to register MBean", e); + } return txn; } @@ -128,12 +136,14 @@ public class Transaction { public static Transaction open(final String name, final short databaseId, final boolean forceDbChange) { Transaction txn = tls.get(); + boolean isNew = false; if (txn == null) { if (s_logger.isTraceEnabled()) { s_logger.trace("Creating the transaction: " + name); } txn = new Transaction(name, false, databaseId); tls.set(txn); + isNew = true; } else if (forceDbChange) { final short currentDbId = txn.getDatabaseId(); if (currentDbId != databaseId) { @@ -142,11 +152,19 @@ public class Transaction { txn = new Transaction(name, false, databaseId); tls.set(txn); + isNew = true; } } txn.takeOver(name, false); - + if (isNew) { + try { + s_logger.debug("Registering txn" + System.identityHashCode(txn)); + JmxUtil.registerMBean("Transaction", "txn" + System.identityHashCode(txn), new TransactionMBeanImpl(txn)); + } catch (Exception e) { + s_logger.error("Unable to register MBean", e); + } + } return txn; } @@ -579,6 +597,12 @@ public class Transaction { if(this._dbId == CONNECTED_DB) { tls.set(_prev); _prev = null; + try { + s_logger.debug("Unregistering txn" + System.identityHashCode(this)); + JmxUtil.unregisterMBean("Transaction", "txn" + System.identityHashCode(this)); + } catch (Exception e) { + s_logger.error("Unable to unregister MBean", e); + } } } @@ -589,7 +613,7 @@ public class Transaction { * @param name * @return true if this close actually closes the connection. false if not. */ - protected boolean close(final String name) { + public boolean close(final String name) { if (_name == null) { // Already cleaned up. if (s_logger.isTraceEnabled()) { s_logger.trace("Already cleaned up." + buildName()); @@ -879,6 +903,14 @@ public class Transaction { rollbackSavepoint(sp); } + public Connection getCurrentConnection() { + return _conn; + } + + public List getStack() { + return _stack; + } + protected Transaction() { _name = null; _conn = null; @@ -888,6 +920,15 @@ public class Transaction { _lockMaster = null; } + @Override + protected void finalize() throws Throwable { + if (!(_conn == null && (_stack == null || _stack.size() == 0))) { + assert (false) : "Oh Alex oh alex...something is wrong with how we're doing this"; + s_logger.error("Something went wrong that a transaction is orphaned before db connection is closed"); + cleanup(); + } + } + protected class StackElement { public String type; public Object ref; diff --git a/utils/src/com/cloud/utils/db/TransactionMBean.java b/utils/src/com/cloud/utils/db/TransactionMBean.java new file mode 100644 index 00000000000..9677bfb945c --- /dev/null +++ b/utils/src/com/cloud/utils/db/TransactionMBean.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.utils.db; + +import java.util.List; + +public interface TransactionMBean { + List getStack(); + + String getName(); + + String getDbConnection(); + +} diff --git a/utils/src/com/cloud/utils/db/TransactionMBeanImpl.java b/utils/src/com/cloud/utils/db/TransactionMBeanImpl.java new file mode 100644 index 00000000000..7908160f277 --- /dev/null +++ b/utils/src/com/cloud/utils/db/TransactionMBeanImpl.java @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.utils.db; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +import javax.management.StandardMBean; + +import com.cloud.utils.db.Transaction.StackElement; + +public class TransactionMBeanImpl extends StandardMBean implements TransactionMBean { + Transaction _txn = null; + + public TransactionMBeanImpl(Transaction txn) { + super(TransactionMBean.class, false); + _txn = txn; + } + + @Override + public List getStack() { + ArrayList elements = new ArrayList(_txn.getStack()); + ArrayList stack = new ArrayList(elements.size()); + + for (StackElement element : elements) { + stack.add(element.toString()); + } + + return stack; + } + + @Override + public String getDbConnection() { + Connection conn = _txn.getCurrentConnection(); + + return (conn != null) ? conn.toString() : "No DB connection"; + } + + + @Override + public String getName() { + return _txn.getName(); + } +} \ No newline at end of file