Added the option for user-confugrable number of data tree change listeners that liste... 78/32378/2
authorJan Medved <jmedved@cisco.com>
Tue, 12 Jan 2016 02:01:39 +0000 (18:01 -0800)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 19 Jan 2016 08:48:38 +0000 (08:48 +0000)
Change-Id: I485b416e262e948545357f5f84da5474c5e14490
Signed-off-by: Jan Medved <jmedved@cisco.com>
benchmark/api/src/main/yang/dsbenchmark.yang
benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/DsbenchmarkProvider.java
benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListener.java [new file with mode: 0644]
benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListenerProvider.java [new file with mode: 0644]

index d56c1852c1a5170e0894499ae039377cab5df341..a5431014630f636d48e9191fedcc2624c5949a47 100644 (file)
@@ -144,19 +144,27 @@ module dsbenchmark {
                 default 100000;
                 description
                   "Number of elements in the OuterList";
-              }
+            }
             leaf innerElements {
                 type uint32;
                 default 1;
                 description
                   "Number of elements in the InnerList";
-              }
+            }
             leaf putsPerTx {
                 type uint32;
                 default 1;
                 description
-                  "Number of write operations (PUT, MERGE, or DELETE) per transaction submit";
-              }
+                  "Number of write operations (PUT, MERGE, or DELETE)
+                   per transaction submit";
+            }
+            leaf listeners {
+                type uint32;
+                default 0;
+                description
+                    "Number of data tree change listeners listening for
+                    changes on the test exec tree.";
+            }
         }
         output {
             leaf status {
@@ -174,32 +182,32 @@ module dsbenchmark {
                 }
                 description
                     "Indicates whether the test finished successfuly";
-               }
+            }
             leaf listBuildTime {
                 type uint32;
-                default 1;
                 description
                   "The time it took to build the list of lists";
-              }
+            }
             leaf execTime {
                 type uint32;
-                default 1;
                 description
                   "The time it took to execute all transactions";
-              }
+            }
             leaf txOk {
                 type uint32;
-                default 1;
                 description
                   "The number of successful transactions";
-              }
+            }
             leaf txError {
                 type uint32;
-                default 1;
                 description
                   "The number of failed transactions";
-              }
-
+            }
+            leaf ntfOk {
+                type uint32;
+                description
+                  "The number of successfully received data tree change notifications";
+            }
         }
     }
 
index 92ac69c0ecc498025c0eae1a2e07c254b78564ff..f40efc3e2dc409e4fa106b472dcdeaf85f8c2641 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.dsbenchmark.listener.DsbenchmarkListenerProvider;
 import org.opendaylight.dsbenchmark.simpletx.SimpletxBaDelete;
 import org.opendaylight.dsbenchmark.simpletx.SimpletxBaRead;
 import org.opendaylight.dsbenchmark.simpletx.SimpletxBaWrite;
@@ -52,14 +53,16 @@ import com.google.common.util.concurrent.Futures;
 public class DsbenchmarkProvider implements BindingAwareProvider, DsbenchmarkService, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(DsbenchmarkProvider.class);
-    private final AtomicReference<ExecStatus> execStatus = new AtomicReference<ExecStatus>( ExecStatus.Idle );
-
     private static final InstanceIdentifier<TestExec> TEST_EXEC_IID = InstanceIdentifier.builder(TestExec.class).build();
     private static final InstanceIdentifier<TestStatus> TEST_STATUS_IID = InstanceIdentifier.builder(TestStatus.class).build();
-    private final DOMDataBroker domDataBroker;
-    private final DataBroker bindingDataBroker;
+
+    private final AtomicReference<ExecStatus> execStatus = new AtomicReference<ExecStatus>( ExecStatus.Idle );
+    private final DsbenchmarkListenerProvider listenerProvider = new DsbenchmarkListenerProvider();
+    private final DOMDataBroker domDataBroker;  // Async DOM Broker for use with all DOM operations
+    private final DataBroker bindingDataBroker; // Async Binding-Aware Broker for use in tx chains; initialized to ping-pong
+                                                // broker in default config (see default-config.xml and dsbenchmark-impl.yang)
+    private DataBroker dataBroker;              // "Legacy" OSGI Data Broker for use in simple transactions
     private RpcRegistration<DsbenchmarkService> dstReg;
-    private DataBroker dataBroker;
 
     private long testsCompleted = 0;
 
@@ -74,6 +77,7 @@ public class DsbenchmarkProvider implements BindingAwareProvider, DsbenchmarkSer
     public void onSessionInitiated(ProviderContext session) {
         this.dataBroker = session.getSALService(DataBroker.class);
         this.dstReg = session.addRpcImplementation( DsbenchmarkService.class, this );
+        listenerProvider.setDataBroker(dataBroker);
         setTestOperData(this.execStatus.get(), testsCompleted);
 
         LOG.info("DsbenchmarkProvider Session Initiated");
@@ -110,6 +114,9 @@ public class DsbenchmarkProvider implements BindingAwareProvider, DsbenchmarkSer
         // Get the appropriate writer based on operation type and data format
         DatastoreAbstractWriter dsWriter = getDatastoreWriter(input);
 
+        // Create listeners on OPERATIONAL and CONFIG test data subtrees
+        listenerProvider.createAndRegisterListeners(input.getListeners().intValue());
+
         long startTime, endTime, listCreateTime, execTime;
 
         startTime = System.nanoTime();
@@ -138,11 +145,15 @@ public class DsbenchmarkProvider implements BindingAwareProvider, DsbenchmarkSer
         setTestOperData( ExecStatus.Idle, testsCompleted);
         execStatus.set(ExecStatus.Idle);
 
+        // Get the number of data change events and cleanup the data change listeners
+        long numEvents = listenerProvider.getEventCountAndDestroyListeners();
+
         StartTestOutput output = new StartTestOutputBuilder()
                 .setStatus(StartTestOutput.Status.OK)
                 .setListBuildTime(listCreateTime)
                 .setExecTime(execTime)
                 .setTxOk((long)dsWriter.getTxOk())
+                .setNtfOk(numEvents)
                 .setTxError((long)dsWriter.getTxError())
                 .build();
 
diff --git a/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListener.java b/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListener.java
new file mode 100644 (file)
index 0000000..02d09f6
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016 Cisco Systems and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.dsbenchmark.listener;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dsbenchmark.rev150105.TestExec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DsbenchmarkListener implements DataTreeChangeListener<TestExec> {
+    private static final Logger LOG = LoggerFactory.getLogger(DsbenchmarkListener.class);
+    private AtomicInteger numEvents = new AtomicInteger(0);
+
+    @Override
+    public void onDataTreeChanged(
+            Collection<DataTreeModification<TestExec>> changes) {
+        // Since we're registering the same DsbenchmarkListener object for both
+        // OPERATIONAL and CONFIG, the onDataTreeChanged() method can be called
+        // from different threads, and we need to use atomic counters.
+
+        final int eventNum = numEvents.incrementAndGet();
+        if(LOG.isDebugEnabled()){
+            logDataTreeChangeEvent(eventNum, changes);
+        }
+    }
+
+    private static synchronized void logDataTreeChangeEvent(int eventNum,
+            Collection<DataTreeModification<TestExec>> changes) {
+        LOG.debug("DsbenchmarkListener-onDataTreeChanged: Event {}", eventNum);
+
+        for(DataTreeModification<TestExec> change : changes) {
+            final DataObjectModification<TestExec> rootNode = change.getRootNode();
+            final ModificationType modType = rootNode.getModificationType();
+            final PathArgument changeId = rootNode.getIdentifier();
+            final Collection<DataObjectModification<? extends DataObject>> modifications = rootNode.getModifiedChildren();
+
+            LOG.debug("    changeId {}, modType {}, mods: {}", changeId, modType, modifications.size());
+
+            for (DataObjectModification<? extends DataObject> mod : modifications) {
+                LOG.debug("      mod-getDataAfter: {}", mod.getDataAfter());
+            }
+        }
+    }
+
+    public int getNumEvents() {
+        return numEvents.get();
+    }
+
+}
diff --git a/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListenerProvider.java b/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListenerProvider.java
new file mode 100644 (file)
index 0000000..7e0146f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016 Cisco Systems and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.dsbenchmark.listener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dsbenchmark.rev150105.TestExec;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DsbenchmarkListenerProvider {
+    private static final Logger LOG = LoggerFactory.getLogger(DsbenchmarkListenerProvider.class);
+    private static final InstanceIdentifier<TestExec> TEST_EXEC_IID = InstanceIdentifier.builder(TestExec.class).build();
+    private final List<ListenerRegistration<DsbenchmarkListener>> listeners = 
+            new ArrayList<ListenerRegistration<DsbenchmarkListener>>();
+    private DataBroker dataBroker;
+
+    public void setDataBroker(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        LOG.info("DsbenchmarkListenerProvider created");
+    }
+
+    public void createAndRegisterListeners(int numListeners) {
+        for(int i = 0; i < numListeners; i++) {
+            DsbenchmarkListener listener = new DsbenchmarkListener();
+            listeners.add(dataBroker.registerDataTreeChangeListener(
+                    new DataTreeIdentifier<TestExec>(LogicalDatastoreType.CONFIGURATION, TEST_EXEC_IID), listener));
+            listeners.add(dataBroker.registerDataTreeChangeListener(
+                    new DataTreeIdentifier<TestExec>(LogicalDatastoreType.OPERATIONAL, TEST_EXEC_IID), listener));
+
+        }
+        LOG.info("DsbenchmarkListenerProvider created {} listeneres", numListeners);
+    }
+
+    public long getEventCountAndDestroyListeners() {
+        long totalEvents = 0;
+
+        for (ListenerRegistration<DsbenchmarkListener> listenerRegistration : listeners) {
+            totalEvents = totalEvents + listenerRegistration.getInstance().getNumEvents();
+            listenerRegistration.close();
+        }
+
+        listeners.clear();
+        totalEvents = totalEvents / 2;  // Each listener is registered 2x: adjust for event double-counting
+        LOG.info("DsbenchmarkListenerProvider destroyed listeneres, total events {}", totalEvents);
+        return totalEvents;
+    }
+}