Add ClientBackedTransaction allocation recording 69/57369/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 25 Apr 2017 10:55:44 +0000 (12:55 +0200)
committerRobert Varga <nite@hq.sk>
Thu, 18 May 2017 15:24:19 +0000 (15:24 +0000)
This patch adds a very simple recording of where a transaction
was allocated, aiding identification of callers who fail to close
transactions.

Change-Id: I9a8743c7a38e83c855102a3a25adecfea8599dfe
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 52c35c0e63343d0009a689c970cafed5d005e337)

opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/ClientBackedDataStore.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/ClientBackedReadTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/ClientBackedReadWriteTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/ClientBackedTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/ClientBackedTransactionChain.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/ClientBackedWriteTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/ClientBackedReadTransactionTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/ClientBackedReadWriteTransactionTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/ClientBackedTransactionChainTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/ClientBackedWriteTransactionTest.java

index 940e5b2..8aebe5b 100644 (file)
@@ -41,21 +41,29 @@ public class ClientBackedDataStore extends AbstractDataStore {
 
     @Override
     public DOMStoreTransactionChain createTransactionChain() {
-        return new ClientBackedTransactionChain(getClient().createLocalHistory());
+        return new ClientBackedTransactionChain(getClient().createLocalHistory(), debugAllocation());
     }
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        return new ClientBackedReadTransaction(getClient().createSnapshot(), null);
+        return new ClientBackedReadTransaction(getClient().createSnapshot(), null, allocationContext());
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new ClientBackedWriteTransaction(getClient().createTransaction());
+        return new ClientBackedWriteTransaction(getClient().createTransaction(), allocationContext());
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        return new ClientBackedReadWriteTransaction(getClient().createTransaction());
+        return new ClientBackedReadWriteTransaction(getClient().createTransaction(), allocationContext());
+    }
+
+    private boolean debugAllocation() {
+        return getActorContext().getDatastoreContext().isTransactionDebugContextEnabled();
+    }
+
+    private Throwable allocationContext() {
+        return debugAllocation() ? new Throwable("allocated at") : null;
     }
 }
index 3d10c39..3cbda25 100644 (file)
@@ -33,8 +33,9 @@ final class ClientBackedReadTransaction extends ClientBackedTransaction<ClientSn
     @SuppressWarnings("unused")
     private volatile ClientBackedTransactionChain parent;
 
-    ClientBackedReadTransaction(final ClientSnapshot delegate, @Nullable final ClientBackedTransactionChain parent) {
-        super(delegate);
+    ClientBackedReadTransaction(final ClientSnapshot delegate, @Nullable final ClientBackedTransactionChain parent,
+        @Nullable final Throwable allocationContext) {
+        super(delegate, allocationContext);
         this.parent = parent;
     }
 
index a1bbe61..9a73fc8 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.cluster.databroker;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.cluster.databroker.actors.dds.ClientTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
@@ -24,8 +25,8 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 final class ClientBackedReadWriteTransaction extends ClientBackedWriteTransaction
         implements DOMStoreReadWriteTransaction {
 
-    ClientBackedReadWriteTransaction(final ClientTransaction delegate) {
-        super(delegate);
+    ClientBackedReadWriteTransaction(final ClientTransaction delegate, @Nullable final Throwable allocationContext) {
+        super(delegate, allocationContext);
     }
 
     @Override
index a01f7a2..5b6a451 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.base.Preconditions;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
 import org.opendaylight.controller.cluster.databroker.actors.dds.AbstractClientHandle;
 import org.opendaylight.controller.cluster.databroker.actors.dds.ClientTransaction;
@@ -35,15 +36,19 @@ abstract class ClientBackedTransaction<T extends AbstractClientHandle<?>> extend
         private static final Logger LOG = LoggerFactory.getLogger(Finalizer.class);
 
         private final AbstractClientHandle<?> transaction;
+        private final Throwable allocationContext;
 
-        private Finalizer(final ClientBackedTransaction<?> referent, final AbstractClientHandle<?> transaction) {
+        private Finalizer(final ClientBackedTransaction<?> referent, final AbstractClientHandle<?> transaction,
+                final Throwable allocationContext) {
             super(referent, QUEUE);
             this.transaction = Preconditions.checkNotNull(transaction);
+            this.allocationContext = allocationContext;
         }
 
         static @Nonnull <T extends AbstractClientHandle<?>> T recordTransaction(
-                @Nonnull final ClientBackedTransaction<T> referent, @Nonnull final T transaction) {
-            FINALIZERS.add(new Finalizer(referent, transaction));
+                @Nonnull final ClientBackedTransaction<T> referent, @Nonnull final T transaction,
+                @Nullable final Throwable allocationContext) {
+            FINALIZERS.add(new Finalizer(referent, transaction, allocationContext));
             return transaction;
         }
 
@@ -51,16 +56,16 @@ abstract class ClientBackedTransaction<T extends AbstractClientHandle<?>> extend
         public void finalizeReferent() {
             FINALIZERS.remove(this);
             if (transaction.abort()) {
-                LOG.info("Aborted orphan transaction {}", transaction);
+                LOG.info("Aborted orphan transaction {}", transaction, allocationContext);
             }
         }
     }
 
     private final T delegate;
 
-    ClientBackedTransaction(final T delegate) {
+    ClientBackedTransaction(final T delegate, final Throwable allocationContext) {
         super(delegate.getIdentifier());
-        this.delegate = Finalizer.recordTransaction(this, delegate);
+        this.delegate = Finalizer.recordTransaction(this, delegate, allocationContext);
     }
 
     final T delegate() {
index db30372..36d1b5d 100644 (file)
@@ -35,24 +35,26 @@ final class ClientBackedTransactionChain implements DOMStoreTransactionChain {
     private final Map<AbstractClientHandle<?>, Boolean> openSnapshots = new WeakHashMap<>();
 
     private final ClientLocalHistory history;
+    private final boolean debugAllocation;
 
-    ClientBackedTransactionChain(final ClientLocalHistory history) {
+    ClientBackedTransactionChain(final ClientLocalHistory history, final boolean debugAllocation) {
         this.history = Preconditions.checkNotNull(history);
+        this.debugAllocation = debugAllocation;
     }
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        return new ClientBackedReadTransaction(createSnapshot(), this);
+        return new ClientBackedReadTransaction(createSnapshot(), this, allocationContext());
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        return new ClientBackedReadWriteTransaction(createTransaction());
+        return new ClientBackedReadWriteTransaction(createTransaction(), allocationContext());
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new ClientBackedWriteTransaction(createTransaction());
+        return new ClientBackedWriteTransaction(createTransaction(), allocationContext());
     }
 
     @Override
@@ -86,6 +88,10 @@ final class ClientBackedTransactionChain implements DOMStoreTransactionChain {
         }
     }
 
+    private Throwable allocationContext() {
+        return debugAllocation ? new Throwable("allocated at") : null;
+    }
+
     private synchronized <T extends AbstractClientHandle<?>> T recordSnapshot(final T snapshot) {
         openSnapshots.put(snapshot, Boolean.TRUE);
         return snapshot;
index 27a671d..56ec344 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.cluster.databroker;
 
+import javax.annotation.Nullable;
 import org.opendaylight.controller.cluster.databroker.actors.dds.ClientTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
@@ -20,8 +21,8 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
  */
 class ClientBackedWriteTransaction extends ClientBackedTransaction<ClientTransaction>
         implements DOMStoreWriteTransaction {
-    ClientBackedWriteTransaction(final ClientTransaction delegate) {
-        super(delegate);
+    ClientBackedWriteTransaction(final ClientTransaction delegate, @Nullable final Throwable allocationContext) {
+        super(delegate, allocationContext);
     }
 
     @Override
index ee8280f..fcba12b 100644 (file)
@@ -49,7 +49,7 @@ public class ClientBackedReadTransactionTest extends ClientBackedTransactionTest
         Mockito.doReturn(Futures.immediateCheckedFuture(Optional.of(data))).when(delegate)
                 .read(YangInstanceIdentifier.EMPTY);
 
-        object = new ClientBackedReadTransaction(delegate, null);
+        object = new ClientBackedReadTransaction(delegate, null, null);
     }
 
     @Test
index bb3b215..db81e5b 100644 (file)
@@ -50,7 +50,7 @@ public class ClientBackedReadWriteTransactionTest
         Mockito.doReturn(Futures.immediateCheckedFuture(Optional.of(data))).when(delegate)
                 .read(YangInstanceIdentifier.EMPTY);
 
-        object = new ClientBackedReadWriteTransaction(delegate);
+        object = new ClientBackedReadWriteTransaction(delegate, null);
     }
 
     @Test
index dab2786..2238bc4 100644 (file)
@@ -49,7 +49,7 @@ public class ClientBackedTransactionChainTest {
         Mockito.when(history.takeSnapshot()).thenReturn(snapshot);
         Mockito.when(history.createTransaction()).thenReturn(transaction);
 
-        chain = new ClientBackedTransactionChain(history);
+        chain = new ClientBackedTransactionChain(history, false);
     }
 
     @Test
index 2f297b5..8091f70 100644 (file)
@@ -37,7 +37,7 @@ public class ClientBackedWriteTransactionTest extends ClientBackedTransactionTes
         Mockito.doReturn(TRANSACTION_ID).when(delegate).getIdentifier();
         Mockito.doReturn(readyCohort).when(delegate).ready();
 
-        object = new ClientBackedWriteTransaction(delegate);
+        object = new ClientBackedWriteTransaction(delegate, null);
     }
 
     @Override

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.