diff --git a/utils/src/com/cloud/utils/db/Transaction.java b/utils/src/com/cloud/utils/db/Transaction.java index f8051b33e14..120c804a398 100755 --- a/utils/src/com/cloud/utils/db/Transaction.java +++ b/utils/src/com/cloud/utils/db/Transaction.java @@ -29,6 +29,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Properties; +import java.util.concurrent.atomic.AtomicLong; import javax.sql.DataSource; @@ -77,8 +78,19 @@ public class Transaction { public static final short CLOUD_DB = 0; public static final short USAGE_DB = 1; public static final short CONNECTED_DB = -1; + + private static final TransactionMBeanImpl s_mbean = new TransactionMBeanImpl(); + static { + try { + JmxUtil.registerMBean("Transaction", "Transaction", s_mbean); + } catch (Exception e) { + s_logger.error("Unable to register mbean for transaction", e); + } + } private final LinkedList _stack; + private static AtomicLong s_id = new AtomicLong(); + private long _id; private final LinkedList> _lockTimes = new LinkedList>(); @@ -89,6 +101,7 @@ public class Transaction { private long _txnTime; private Statement _stmt; private final Merovingian _lockMaster; + private String _creator; private Transaction _prev = null; @@ -125,12 +138,8 @@ 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); - } + s_logger.debug("Registering txn" + txn.getId()); + s_mbean.addTransaction(txn); return txn; } @@ -162,12 +171,8 @@ public class Transaction { 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); - } + s_logger.debug("Registering txn" + txn.getId()); + s_mbean.addTransaction(txn); } return txn; } @@ -307,6 +312,16 @@ public class Transaction { _txn = false; _dbId = databaseId; _lockMaster = forLocking ? null : new Merovingian(_dbId); + _id = s_id.incrementAndGet(); + _creator = Thread.currentThread().getName(); + } + + public String getCreator() { + return _creator; + } + + public long getId() { + return _id; } public String getName() { @@ -601,12 +616,8 @@ 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); - } + s_logger.debug("Unregistering txn" + getId()); + s_mbean.removeTransaction(this); } } diff --git a/utils/src/com/cloud/utils/db/TransactionMBean.java b/utils/src/com/cloud/utils/db/TransactionMBean.java index 7deffb5f523..25925dbe1ca 100644 --- a/utils/src/com/cloud/utils/db/TransactionMBean.java +++ b/utils/src/com/cloud/utils/db/TransactionMBean.java @@ -20,12 +20,12 @@ package com.cloud.utils.db; import java.util.List; public interface TransactionMBean { - List getStack(); + int getTransactionCount(); - String getName(); + int getActiveTransactionCount(); - String getDbConnection(); + List getTransactions(); + + List getActiveTransactions(); - String getThreadName(); - } diff --git a/utils/src/com/cloud/utils/db/TransactionMBeanImpl.java b/utils/src/com/cloud/utils/db/TransactionMBeanImpl.java index 3a693dd1c83..fdff868dbc6 100644 --- a/utils/src/com/cloud/utils/db/TransactionMBeanImpl.java +++ b/utils/src/com/cloud/utils/db/TransactionMBeanImpl.java @@ -17,52 +17,80 @@ */ package com.cloud.utils.db; -import java.sql.Connection; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.management.StandardMBean; import com.cloud.utils.db.Transaction.StackElement; public class TransactionMBeanImpl extends StandardMBean implements TransactionMBean { - Transaction _txn = null; - String _threadName = null; - public TransactionMBeanImpl(Transaction txn) { + Map _txns = new ConcurrentHashMap(); + + public TransactionMBeanImpl() { super(TransactionMBean.class, false); - _txn = txn; - _threadName = Thread.currentThread().getName(); + } + + public void addTransaction(Transaction txn) { + _txns.put(txn.getId(), txn); + } + + public void removeTransaction(Transaction txn) { + _txns.remove(txn.getId()); } @Override - public String getThreadName() { - return _threadName; + public int getTransactionCount() { + return _txns.size(); } @Override - public List getStack() { - ArrayList elements = new ArrayList(_txn.getStack()); - ArrayList stack = new ArrayList(elements.size()); - - for (StackElement element : elements) { - stack.add(element.toString()); + public int getActiveTransactionCount() { + int count = 0; + for (Transaction txn : _txns.values()) { + if (txn.getStack().size() > 0) { + count++; + } } - - return stack; + return count; } @Override - public String getDbConnection() { - Connection conn = _txn.getCurrentConnection(); - - return (conn != null) ? conn.toString() : "No DB connection"; + public List getTransactions() { + ArrayList txns = new ArrayList(); + for (Transaction info : _txns.values()) { + txns.add(toString(info)); + } + return txns; } - @Override - public String getName() { - return _txn.getName(); + public List getActiveTransactions() { + ArrayList txns = new ArrayList(); + for (Transaction txn : _txns.values()) { + if (txn.getStack().size() > 0 || txn.getCurrentConnection() != null) { + txns.add(toString(txn)); + } + } + return txns; } + protected String toString(Transaction txn) { + StringBuilder buff = new StringBuilder("[Name="); + buff.append(txn.getName()); + buff.append("; Creator="); + buff.append(txn.getCreator()); + buff.append("; DB="); + buff.append(txn.getCurrentConnection()); + buff.append("; Stack="); + for (StackElement element : txn.getStack()) { + buff.append(",").append(element.toString()); + } + buff.append("]"); + + return buff.toString(); + } } \ No newline at end of file