2 * Copyright (c) 2017 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.md.sal.trace.closetracker.impl;
10 import java.util.Arrays;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
17 import java.util.concurrent.ConcurrentSkipListSet;
18 import javax.annotation.concurrent.ThreadSafe;
21 * Registry of {@link CloseTracked} instances.
23 * @author Michael Vorburger.ch
26 public class CloseTrackedRegistry<T extends CloseTracked<T>> {
28 // unused OK for now, at least we'll be able to see this in HPROF heap dumps and know what is which
29 private final @SuppressWarnings("unused") Object anchor;
30 private final @SuppressWarnings("unused") String createDescription;
32 private final Set<CloseTracked<T>> tracked = new ConcurrentSkipListSet<>(
33 (o1, o2) -> Integer.compare(System.identityHashCode(o1), System.identityHashCode(o2)));
35 private final boolean isDebugContextEnabled;
41 * object where this registry is stored in, used for human output in
42 * logging and other output
43 * @param createDescription
44 * description of creator of instances of this registry, typically
45 * e.g. name of method in the anchor class
46 * @param isDebugContextEnabled
47 * whether or not the call stack should be preserved; this is (of
48 * course) an expensive operation, and should only be used during
51 public CloseTrackedRegistry(Object anchor, String createDescription, boolean isDebugContextEnabled) {
53 this.createDescription = createDescription;
54 this.isDebugContextEnabled = isDebugContextEnabled;
57 public boolean isDebugContextEnabled() {
58 return isDebugContextEnabled;
61 // package protected, not public; only CloseTrackedTrait invokes this
62 void add(CloseTracked<T> closeTracked) {
63 tracked.add(closeTracked);
66 // package protected, not public; only CloseTrackedTrait invokes this
67 void remove(CloseTracked<T> closeTracked) {
68 tracked.remove(closeTracked);
72 * Creates and returns a "report" of (currently) tracked but not (yet) closed
75 * @return Map where key is the StackTraceElement[] identifying a unique
76 * allocation contexts (or an empty List if debugContextEnabled is false),
77 * and value is the number of open instances created at that point.
79 public Map<List<StackTraceElement>, Long> getAllUnique() {
80 Map<List<StackTraceElement>,Long> mapToReturn = new HashMap<>();
81 Set<CloseTracked<T>> copyOfTracked = new HashSet<>(tracked);
82 for (CloseTracked<T> closeTracked : copyOfTracked) {
83 final StackTraceElement[] stackTraceArray = closeTracked.getAllocationContextStackTrace();
84 List<StackTraceElement> stackTraceElements =
85 stackTraceArray != null ? Arrays.asList(stackTraceArray) : Collections.emptyList();
86 mapToReturn.merge(stackTraceElements, 1L, (oldValue, value) -> oldValue + 1);