Bug 9060: TracingBroker printOpenTransactions
[controller.git] / opendaylight / md-sal / mdsal-trace / dom-impl / src / main / java / org / opendaylight / controller / md / sal / trace / closetracker / impl / CloseTrackedRegistry.java
index 9364a57ae0e6765f6d6b1aedf840385084d2badd..4e608396303b94e2dd1bca31130349a856ac7ebc 100644 (file)
@@ -7,6 +7,15 @@
  */
 package org.opendaylight.controller.md.sal.trace.closetracker.impl;
 
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentSkipListSet;
 import javax.annotation.concurrent.ThreadSafe;
@@ -19,12 +28,11 @@ import javax.annotation.concurrent.ThreadSafe;
 @ThreadSafe
 public class CloseTrackedRegistry<T extends CloseTracked<T>> {
 
-    // unused OK for now, at least we'll be able to see this in HPROF heap dumps and know what is which
-    private final @SuppressWarnings("unused") Object anchor;
-    private final @SuppressWarnings("unused") String createDescription;
+    private final Object anchor;
+    private final String createDescription;
 
     private final Set<CloseTracked<T>> tracked = new ConcurrentSkipListSet<>(
-        (o1, o2) -> o1.getObjectCreated().compareTo(o2.getObjectCreated()));
+        (o1, o2) -> Integer.compare(System.identityHashCode(o1), System.identityHashCode(o2)));
 
     private final boolean isDebugContextEnabled;
 
@@ -52,6 +60,14 @@ public class CloseTrackedRegistry<T extends CloseTracked<T>> {
         return isDebugContextEnabled;
     }
 
+    public Object getAnchor() {
+        return anchor;
+    }
+
+    public String getCreateDescription() {
+        return createDescription;
+    }
+
     // package protected, not public; only CloseTrackedTrait invokes this
     void add(CloseTracked<T> closeTracked) {
         tracked.add(closeTracked);
@@ -62,8 +78,37 @@ public class CloseTrackedRegistry<T extends CloseTracked<T>> {
         tracked.remove(closeTracked);
     }
 
-    // TODO Later add methods to dump & query what's not closed, by creation time, incl. creation stack trace
+    /**
+     * Creates and returns a "report" of (currently) tracked but not (yet) closed
+     * instances.
+     *
+     * @return Set of CloseTrackedRegistryReportEntry, of which each the stack trace
+     *         element identifies a unique allocation context (or an empty List if
+     *         debugContextEnabled is false), and value is the number of open
+     *         instances created at that place in the code.
+     */
+    public Set<CloseTrackedRegistryReportEntry<T>> getAllUnique() {
+        Map<List<StackTraceElement>, Long> map = new HashMap<>();
+        Set<CloseTracked<T>> copyOfTracked = new HashSet<>(tracked);
+        for (CloseTracked<T> closeTracked : copyOfTracked) {
+            final StackTraceElement[] stackTraceArray = closeTracked.getAllocationContextStackTrace();
+            List<StackTraceElement> stackTraceElements =
+                    stackTraceArray != null ? Arrays.asList(stackTraceArray) : Collections.emptyList();
+            map.merge(stackTraceElements, 1L, (oldValue, value) -> oldValue + 1);
+        }
 
-    // TODO we could even support add/close of Object instead of CloseTracked, by creating a wrapper?
+        Set<CloseTrackedRegistryReportEntry<T>> report = new HashSet<>();
+        map.forEach((stackTraceElements, number) -> {
+            copyOfTracked.stream().filter(closeTracked -> {
+                StackTraceElement[] closeTrackedStackTraceArray = closeTracked.getAllocationContextStackTrace();
+                List<StackTraceElement> closeTrackedStackTraceElements =
+                        closeTrackedStackTraceArray != null ? asList(closeTrackedStackTraceArray) : emptyList();
+                return closeTrackedStackTraceElements.equals(stackTraceElements);
+            }).findAny().ifPresent(exampleCloseTracked -> {
+                report.add(new CloseTrackedRegistryReportEntry<>(exampleCloseTracked, number, stackTraceElements));
+            });
+        });
+        return report;
+    }
 
 }