From: Jan Medved Date: Tue, 12 Jan 2016 02:01:39 +0000 (-0800) Subject: Added the option for user-confugrable number of data tree change listeners that liste... X-Git-Tag: release/boron~432 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=6e76bb10e6a34b2d932dc57546cafcc74401ba9c Added the option for user-confugrable number of data tree change listeners that listen on the text-exec data tree. Change-Id: I485b416e262e948545357f5f84da5474c5e14490 Signed-off-by: Jan Medved --- diff --git a/benchmark/api/src/main/yang/dsbenchmark.yang b/benchmark/api/src/main/yang/dsbenchmark.yang index d56c1852c1..a543101463 100644 --- a/benchmark/api/src/main/yang/dsbenchmark.yang +++ b/benchmark/api/src/main/yang/dsbenchmark.yang @@ -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"; + } } } diff --git a/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/DsbenchmarkProvider.java b/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/DsbenchmarkProvider.java index 92ac69c0ec..f40efc3e2d 100644 --- a/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/DsbenchmarkProvider.java +++ b/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/DsbenchmarkProvider.java @@ -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 = new AtomicReference( ExecStatus.Idle ); - private static final InstanceIdentifier TEST_EXEC_IID = InstanceIdentifier.builder(TestExec.class).build(); private static final InstanceIdentifier TEST_STATUS_IID = InstanceIdentifier.builder(TestStatus.class).build(); - private final DOMDataBroker domDataBroker; - private final DataBroker bindingDataBroker; + + private final AtomicReference execStatus = new AtomicReference( 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 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 index 0000000000..02d09f6f47 --- /dev/null +++ b/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListener.java @@ -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 { + private static final Logger LOG = LoggerFactory.getLogger(DsbenchmarkListener.class); + private AtomicInteger numEvents = new AtomicInteger(0); + + @Override + public void onDataTreeChanged( + Collection> 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> changes) { + LOG.debug("DsbenchmarkListener-onDataTreeChanged: Event {}", eventNum); + + for(DataTreeModification change : changes) { + final DataObjectModification rootNode = change.getRootNode(); + final ModificationType modType = rootNode.getModificationType(); + final PathArgument changeId = rootNode.getIdentifier(); + final Collection> modifications = rootNode.getModifiedChildren(); + + LOG.debug(" changeId {}, modType {}, mods: {}", changeId, modType, modifications.size()); + + for (DataObjectModification 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 index 0000000000..7e0146f991 --- /dev/null +++ b/benchmark/dsbenchmark/src/main/java/org/opendaylight/dsbenchmark/listener/DsbenchmarkListenerProvider.java @@ -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 TEST_EXEC_IID = InstanceIdentifier.builder(TestExec.class).build(); + private final List> listeners = + new ArrayList>(); + 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(LogicalDatastoreType.CONFIGURATION, TEST_EXEC_IID), listener)); + listeners.add(dataBroker.registerDataTreeChangeListener( + new DataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, TEST_EXEC_IID), listener)); + + } + LOG.info("DsbenchmarkListenerProvider created {} listeneres", numListeners); + } + + public long getEventCountAndDestroyListeners() { + long totalEvents = 0; + + for (ListenerRegistration 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; + } +}