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 {
}
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";
+ }
}
}
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;
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;
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");
// 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();
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();
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}