Rename DOMDataTreeChangeService
[mdsal.git] / trace / mdsal-trace-impl / src / main / java / org / opendaylight / mdsal / trace / impl / TracingBroker.java
index 29e99af3a9cdaba825a1775bd5d956eb308d62c6..b7b528b636de630f645554e18e5d6fb1a814a1c0 100644 (file)
@@ -9,29 +9,21 @@ package org.opendaylight.mdsal.trace.impl;
 
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.MutableClassToInstanceMap;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.ClusteredDOMDataTreeChangeListener;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
-import org.opendaylight.mdsal.dom.api.DOMDataBrokerExtension;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 import org.opendaylight.mdsal.trace.api.TracingDOMDataBroker;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsaltrace.rev160908.Config;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -40,7 +32,6 @@ import org.slf4j.LoggerFactory;
 
 @SuppressWarnings("checkstyle:JavadocStyle")
 //...because otherwise it whines about the elements in the @code block even though it's completely valid Javadoc
-
 /**
  * TracingBroker logs "write" operations and listener registrations to the md-sal. It logs the instance identifier path,
  * the objects themselves, as well as the stack trace of the call invoking the registration or write operation.
@@ -94,16 +85,13 @@ import org.slf4j.LoggerFactory;
  *        watchRegistrations and allow all registrations to be logged.
  *     </li>
  * </ul>
- *
  */
 public class TracingBroker implements TracingDOMDataBroker {
-    @SuppressFBWarnings("SLF4J_LOGGER_SHOULD_BE_PRIVATE")
-    static final Logger LOG = LoggerFactory.getLogger(TracingBroker.class);
+    private static final Logger LOG = LoggerFactory.getLogger(TracingBroker.class);
 
     private static final int STACK_TRACE_FIRST_RELEVANT_FRAME = 2;
 
-    private final String type; // "default" VS "pingpong"
-    private final BindingNormalizedNodeSerializer codec;
+    private final BindingCodecTree codec;
     private final DOMDataBroker delegate;
     private final List<Watch> registrationWatches = new ArrayList<>();
     private final List<Watch> writeWatches = new ArrayList<>();
@@ -118,19 +106,18 @@ public class TracingBroker implements TracingDOMDataBroker {
         final String iidString;
         final LogicalDatastoreType store;
 
-        Watch(String iidString, LogicalDatastoreType storeOrNull) {
-            this.store = storeOrNull;
+        Watch(final String iidString, final LogicalDatastoreType storeOrNull) {
+            store = storeOrNull;
             this.iidString = iidString;
         }
 
-        private String toIidCompString(YangInstanceIdentifier iid) {
+        private String toIidCompString(final YangInstanceIdentifier iid) {
             StringBuilder builder = new StringBuilder();
             toPathString(iid, builder);
-            builder.append('/');
-            return builder.toString();
+            return builder.append('/').toString();
         }
 
-        private boolean isParent(String parent, String child) {
+        private boolean isParent(final String parent, final String child) {
             int parentOffset = 0;
             if (parent.length() > 0 && parent.charAt(0) == '<') {
                 parentOffset = parent.indexOf('>') + 1;
@@ -145,7 +132,7 @@ public class TracingBroker implements TracingDOMDataBroker {
         }
 
         @SuppressWarnings({ "checkstyle:hiddenField", "hiding" })
-        public boolean subtreesOverlap(YangInstanceIdentifier iid, LogicalDatastoreType store) {
+        public boolean subtreesOverlap(final YangInstanceIdentifier iid, final LogicalDatastoreType store) {
             if (this.store != null && !this.store.equals(store)) {
                 return false;
             }
@@ -155,7 +142,7 @@ public class TracingBroker implements TracingDOMDataBroker {
         }
 
         @SuppressWarnings({ "checkstyle:hiddenField", "hiding" })
-        public boolean eventIsOfInterest(YangInstanceIdentifier iid, LogicalDatastoreType store) {
+        public boolean eventIsOfInterest(final YangInstanceIdentifier iid, final LogicalDatastoreType store) {
             if (this.store != null && !this.store.equals(store)) {
                 return false;
             }
@@ -164,27 +151,22 @@ public class TracingBroker implements TracingDOMDataBroker {
         }
     }
 
-    public TracingBroker(String type, DOMDataBroker delegate, Config config, BindingNormalizedNodeSerializer codec) {
-        this.type = requireNonNull(type, "type");
+    public TracingBroker(final DOMDataBroker delegate, final Config config, final BindingCodecTree codec) {
         this.delegate = requireNonNull(delegate, "delegate");
         this.codec = requireNonNull(codec, "codec");
         configure(config);
 
-        if (config.isTransactionDebugContextEnabled() != null) {
-            this.isDebugging = config.isTransactionDebugContextEnabled();
-        } else {
-            this.isDebugging = false;
-        }
+        isDebugging = Boolean.TRUE.equals(config.getTransactionDebugContextEnabled());
         final String db = "DataBroker";
-        this.transactionChainsRegistry     = new CloseTrackedRegistry<>(db, "createTransactionChain()", isDebugging);
-        this.readOnlyTransactionsRegistry  = new CloseTrackedRegistry<>(db, "newReadOnlyTransaction()", isDebugging);
-        this.writeTransactionsRegistry     = new CloseTrackedRegistry<>(db, "newWriteOnlyTransaction()", isDebugging);
-        this.readWriteTransactionsRegistry = new CloseTrackedRegistry<>(db, "newReadWriteTransaction()", isDebugging);
+        transactionChainsRegistry     = new CloseTrackedRegistry<>(db, "createTransactionChain()", isDebugging);
+        readOnlyTransactionsRegistry  = new CloseTrackedRegistry<>(db, "newReadOnlyTransaction()", isDebugging);
+        writeTransactionsRegistry     = new CloseTrackedRegistry<>(db, "newWriteOnlyTransaction()", isDebugging);
+        readWriteTransactionsRegistry = new CloseTrackedRegistry<>(db, "newReadWriteTransaction()", isDebugging);
     }
 
-    private void configure(Config config) {
+    private void configure(final Config config) {
         registrationWatches.clear();
-        List<String> paths = config.getRegistrationWatches();
+        Set<String> paths = config.getRegistrationWatches();
         if (paths != null) {
             for (String path : paths) {
                 watchRegistrations(path, null);
@@ -205,7 +187,7 @@ public class TracingBroker implements TracingDOMDataBroker {
      * @param iidString the iid path of the root of the subtree
      * @param store Which LogicalDataStore? or null for both
      */
-    public void watchRegistrations(String iidString, LogicalDatastoreType store) {
+    public void watchRegistrations(final String iidString, final LogicalDatastoreType store) {
         LOG.info("Watching registrations to {} in {}", iidString, store);
         registrationWatches.add(new Watch(iidString, store));
     }
@@ -215,13 +197,13 @@ public class TracingBroker implements TracingDOMDataBroker {
      * @param iidString the iid path of the root of the subtree
      * @param store Which LogicalDataStore? or null for both
      */
-    public void watchWrites(String iidString, LogicalDatastoreType store) {
+    public void watchWrites(final String iidString, final LogicalDatastoreType store) {
         LOG.info("Watching writes to {} in {}", iidString, store);
         Watch watch = new Watch(iidString, store);
         writeWatches.add(watch);
     }
 
-    private boolean isRegistrationWatched(YangInstanceIdentifier iid, LogicalDatastoreType store) {
+    private boolean isRegistrationWatched(final YangInstanceIdentifier iid, final LogicalDatastoreType store) {
         if (registrationWatches.isEmpty()) {
             return true;
         }
@@ -235,7 +217,7 @@ public class TracingBroker implements TracingDOMDataBroker {
         return false;
     }
 
-    boolean isWriteWatched(YangInstanceIdentifier iid, LogicalDatastoreType store) {
+    boolean isWriteWatched(final YangInstanceIdentifier iid, final LogicalDatastoreType store) {
         if (writeWatches.isEmpty()) {
             return true;
         }
@@ -249,21 +231,21 @@ public class TracingBroker implements TracingDOMDataBroker {
         return false;
     }
 
-    static void toPathString(InstanceIdentifier<? extends DataObject> iid, StringBuilder builder) {
-        for (InstanceIdentifier.PathArgument pathArg : iid.getPathArguments()) {
-            builder.append('/').append(pathArg.getType().getSimpleName());
+    static void toPathString(final InstanceIdentifier<? extends DataObject> iid, final StringBuilder builder) {
+        for (var pathArg : iid.getPathArguments()) {
+            builder.append('/').append(pathArg.type().getSimpleName());
         }
     }
 
-    String toPathString(YangInstanceIdentifier  yiid) {
+    String toPathString(final YangInstanceIdentifier  yiid) {
         StringBuilder sb = new StringBuilder();
         toPathString(yiid, sb);
         return sb.toString();
     }
 
 
-    private void toPathString(YangInstanceIdentifier yiid, StringBuilder sb) {
-        InstanceIdentifier<?> iid = codec.fromYangInstanceIdentifier(yiid);
+    private void toPathString(final YangInstanceIdentifier yiid, final StringBuilder sb) {
+        InstanceIdentifier<?> iid = codec.getInstanceIdentifierCodec().toBinding(yiid);
         if (null == iid) {
             reconstructIidPathString(yiid, sb);
         } else {
@@ -271,13 +253,9 @@ public class TracingBroker implements TracingDOMDataBroker {
         }
     }
 
-    private static void reconstructIidPathString(YangInstanceIdentifier yiid, StringBuilder sb) {
+    private static void reconstructIidPathString(final YangInstanceIdentifier yiid, final StringBuilder sb) {
         sb.append("<RECONSTRUCTED FROM: \"").append(yiid.toString()).append("\">");
         for (YangInstanceIdentifier.PathArgument pathArg : yiid.getPathArguments()) {
-            if (pathArg instanceof YangInstanceIdentifier.AugmentationIdentifier) {
-                sb.append('/').append("AUGMENTATION");
-                continue;
-            }
             sb.append('/').append(pathArg.getNodeType().getLocalName());
         }
     }
@@ -305,15 +283,13 @@ public class TracingBroker implements TracingDOMDataBroker {
     }
 
     @Override
-    public DOMTransactionChain createTransactionChain(DOMTransactionChainListener transactionChainListener) {
-        return new TracingTransactionChain(delegate.createTransactionChain(transactionChainListener), this,
-            transactionChainsRegistry);
+    public DOMTransactionChain createTransactionChain() {
+        return new TracingTransactionChain(delegate.createTransactionChain(), this, transactionChainsRegistry);
     }
 
     @Override
-    public DOMTransactionChain createMergingTransactionChain(DOMTransactionChainListener transactionChainListener) {
-        return new TracingTransactionChain(delegate.createMergingTransactionChain(transactionChainListener), this,
-            transactionChainsRegistry);
+    public DOMTransactionChain createMergingTransactionChain() {
+        return new TracingTransactionChain(delegate.createMergingTransactionChain(), this, transactionChainsRegistry);
     }
 
     @Override
@@ -322,44 +298,34 @@ public class TracingBroker implements TracingDOMDataBroker {
     }
 
     @Override
-    public ClassToInstanceMap<DOMDataBrokerExtension> getExtensions() {
-        final ClassToInstanceMap<DOMDataBrokerExtension> delegateExt = delegate.getExtensions();
-        final DOMDataTreeChangeService treeChangeSvc = delegateExt.getInstance(DOMDataTreeChangeService.class);
-        if (treeChangeSvc == null) {
-            return delegateExt;
-        }
-
-        final ClassToInstanceMap<DOMDataBrokerExtension> res = MutableClassToInstanceMap.create(delegateExt);
-        res.put(DOMDataTreeChangeService.class, new DOMDataTreeChangeService() {
-            @Override
-            public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerDataTreeChangeListener(
-                    DOMDataTreeIdentifier domDataTreeIdentifier, L listener) {
-                if (isRegistrationWatched(domDataTreeIdentifier.getRootIdentifier(),
-                        domDataTreeIdentifier.getDatastoreType())) {
+    public <T extends Extension> T extension(final Class<T> type) {
+        final var ext = delegate.extension(type);
+        if (DataTreeChangeExtension.class.equals(type) && ext instanceof DataTreeChangeExtension treeChange) {
+            return type.cast((DataTreeChangeExtension) (domDataTreeIdentifier, listener) -> {
+                final var rootId = domDataTreeIdentifier.path();
+                if (isRegistrationWatched(rootId, domDataTreeIdentifier.datastore())) {
                     LOG.warn("{} registration (registerDataTreeChangeListener) for {} from {}.",
-                            listener instanceof ClusteredDOMDataTreeChangeListener ? "Clustered" : "Non-clustered",
-                            toPathString(domDataTreeIdentifier.getRootIdentifier()), getStackSummary());
+                        listener instanceof ClusteredDOMDataTreeChangeListener ? "Clustered" : "Non-clustered",
+                            toPathString(rootId), getStackSummary());
                 }
-                return treeChangeSvc.registerDataTreeChangeListener(domDataTreeIdentifier, listener);
-            }
-        });
-
-        return res;
+                return treeChange.registerDataTreeChangeListener(domDataTreeIdentifier, listener);
+            });
+        }
+        return ext;
     }
 
     @Override
-    public boolean printOpenTransactions(PrintStream ps, int minOpenTXs) {
+    public boolean printOpenTransactions(final PrintStream ps, final int minOpenTXs) {
         if (transactionChainsRegistry.getAllUnique().isEmpty()
             && readOnlyTransactionsRegistry.getAllUnique().isEmpty()
             && writeTransactionsRegistry.getAllUnique().isEmpty()
             && readWriteTransactionsRegistry.getAllUnique().isEmpty()) {
 
-            ps.println(type + ": No open transactions, great!");
+            ps.println("No open transactions, great!");
             return false;
         }
 
-        ps.println(type + ": " + getClass().getSimpleName()
-                 + " found some not yet (or never..) closed transaction[chain]s!");
+        ps.println(getClass().getSimpleName() + " found some not yet (or never..) closed transaction[chain]s!");
         ps.println("[NB: If no stack traces are shown below, then "
                  + "enable transaction-debug-context-enabled in mdsaltrace_config.xml]");
         ps.println();
@@ -391,8 +357,24 @@ public class TracingBroker implements TracingDOMDataBroker {
         return hasFound;
     }
 
-    private <T extends CloseTracked<T>> boolean print(
-            CloseTrackedRegistry<T> registry, PrintStream ps, String indent, int minOpenTransactions) {
+    final void logEmptySet(final YangInstanceIdentifier yiid) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Empty data set write to {}", toPathString(yiid));
+        }
+    }
+
+    @SuppressFBWarnings(value = "SLF4J_SIGN_ONLY_FORMAT", justification = "pre-formatted logs")
+    static final void logOperations(final Object identifier, final List<?> operations) {
+        if (LOG.isWarnEnabled()) {
+            LOG.warn("Transaction {} contains the following operations:", identifier);
+            for (var operation : operations) {
+                LOG.warn("{}", operation);
+            }
+        }
+    }
+
+    private <T extends CloseTracked<T>> boolean print(final CloseTrackedRegistry<T> registry, final PrintStream ps,
+            final String indent, final int minOpenTransactions) {
         Set<CloseTrackedRegistryReportEntry<T>> unsorted = registry.getAllUnique();
         if (unsorted.size() < minOpenTransactions) {
             return false;
@@ -415,7 +397,8 @@ public class TracingBroker implements TracingDOMDataBroker {
         return true;
     }
 
-    private void printStackTraceElements(PrintStream ps, String indent, List<StackTraceElement> stackTraceElements) {
+    private void printStackTraceElements(final PrintStream ps, final String indent,
+            final List<StackTraceElement> stackTraceElements) {
         boolean ellipsis = false;
         for (final StackTraceElement stackTraceElement : stackTraceElements) {
             if (isStackTraceElementInteresting(stackTraceElement)) {
@@ -428,7 +411,7 @@ public class TracingBroker implements TracingDOMDataBroker {
         }
     }
 
-    private boolean isStackTraceElementInteresting(StackTraceElement element) {
+    private boolean isStackTraceElementInteresting(final StackTraceElement element) {
         final String className = element.getClassName();
         return !className.startsWith(getClass().getPackage().getName())
             && !className.startsWith(CloseTracked.class.getPackage().getName())