<snapshot>
<required-capabilities>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:bgpcep:data:change:counter?module=odl-data-change-counter-cfg&revision=2014-08-15</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:bgpcep:data:change:counter?module=odl-data-change-counter-cfg&revision=2016-03-15</capability>
</required-capabilities>
<configuration>
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgpcep:data:change:counter">prefix:data-change-counter-impl</type>
- <name>data-change-counter-singleton</name>
+ <name>data-change-counter</name>
+ <counter-id>data-change-counter</counter-id>
<data-provider>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
<name>binding-data-broker</name>
@Override
public void customValidation() {
+ JmxAttributeValidationException.checkNotNull(getCounterId(), "value is not set.", counterIdJmxAttribute);
JmxAttributeValidationException.checkNotNull(getTopologyName(), "value is not set.", topologyNameJmxAttribute);
}
@Override
public java.lang.AutoCloseable createInstance() {
- final TopologyDataChangeCounter counter = new TopologyDataChangeCounter(getDataProviderDependency());
+ final TopologyDataChangeCounter counter = new TopologyDataChangeCounter(getDataProviderDependency(), getCounterId());
final InstanceIdentifier<Topology> topoIId = InstanceIdentifier.builder(NetworkTopology.class)
.child(Topology.class, new TopologyKey(new TopologyId(getTopologyName()))).build();
final ListenerRegistration<DataChangeListener> registration = getDataProviderDependency().registerDataChangeListener(
*/
package org.opendaylight.controller.config.yang.bgpcep.data.change.counter;
-import static com.google.common.base.Preconditions.checkArgument;
-
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.osgi.framework.BundleContext;
-
public class DataChangeCounterImplModuleFactory extends org.opendaylight.controller.config.yang.bgpcep.data.change.counter.AbstractDataChangeCounterImplModuleFactory {
- public static final String SINGLETON_NAME = "data-change-counter-singleton";
-
- @Override
- public DataChangeCounterImplModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
- DataChangeCounterImplModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) {
- checkArgument(SINGLETON_NAME.equals(instanceName), "Illegal instance name '" + instanceName
- + "', only allowed name is " + SINGLETON_NAME);
- return super.instantiateModule(instanceName, dependencyResolver, oldModule,
- oldInstance, bundleContext);
- }
- @Override
- public DataChangeCounterImplModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
- BundleContext bundleContext) {
- checkArgument(SINGLETON_NAME.equals(instanceName), "Illegal instance name '" + instanceName
- + "', only allowed name is " + SINGLETON_NAME);
- return super.instantiateModule(instanceName, dependencyResolver, bundleContext);
- }
}
import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev140815.DataChangeCounter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev140815.DataChangeCounterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.DataChangeCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.data.change.counter.Counter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.data.change.counter.CounterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.data.change.counter.CounterKey;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
private static final Logger LOG = LoggerFactory.getLogger(TopologyDataChangeCounter.class);
- protected static final InstanceIdentifier<DataChangeCounter> IID = InstanceIdentifier
- .builder(DataChangeCounter.class).build();
-
private final DataBroker dataBroker;
+ private final String counterId;
+ private final InstanceIdentifier<Counter> counterInstanceId;
private final BindingTransactionChain chain;
private final AtomicLong count;
- public TopologyDataChangeCounter(final DataBroker dataBroker) {
+ public TopologyDataChangeCounter(final DataBroker dataBroker, final String counterId) {
this.dataBroker = dataBroker;
this.chain = this.dataBroker.createTransactionChain(this);
+ this.counterId = counterId;
+ this.counterInstanceId = InstanceIdentifier.builder(DataChangeCounter.class)
+ .child(Counter.class, new CounterKey(this.counterId)).build();
this.count = new AtomicLong(0);
putCount(this.count.get());
- LOG.debug("Data change counter initiated");
+ LOG.debug("Data change counter {} initiated", this.counterId);
}
@Override
public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
putCount(this.count.incrementAndGet());
- LOG.debug("Data change #{}", this.count.get());
+ LOG.debug("Data change #{} for counter {}", this.count.get(), this.counterId);
}
public void close() {
final WriteTransaction wTx = this.dataBroker.newWriteOnlyTransaction();
- wTx.delete(LogicalDatastoreType.OPERATIONAL, IID);
+ wTx.delete(LogicalDatastoreType.OPERATIONAL, this.counterInstanceId);
try {
wTx.submit().checkedGet();
} catch (TransactionCommitFailedException except) {
- LOG.warn("Error on remove data change counter{}", IID.toString(), except);
+ LOG.warn("Error on remove data change counter {}", this.counterId, except);
}
this.chain.close();
- LOG.debug("Data change counter removed");
+ LOG.debug("Data change counter {} removed", this.counterId);
}
private void putCount(final long count) {
final WriteTransaction wTx = this.chain.newWriteOnlyTransaction();
- wTx.put(LogicalDatastoreType.OPERATIONAL, IID, new DataChangeCounterBuilder().setCount(count).build());
+ Counter counter = new CounterBuilder().setId(this.counterId).setCount(count).build();
+ wTx.put(LogicalDatastoreType.OPERATIONAL, this.counterInstanceId, counter);
wTx.submit();
}
accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html";
+ revision "2016-03-15" {
+ description
+ "Updated to support multiple instances.";
+ }
revision "2014-08-15" {
description
"Initial revision.";
}
container data-change-counter {
- leaf count {
- type uint32;
- description
- "The number of data changes.";
+ config false;
+
+ list counter {
+ leaf id {
+ type string;
+ }
+ key id;
+
+ leaf count {
+ type uint32;
+ description
+ "The number of data changes.";
+ }
}
}
- }
\ No newline at end of file
+ }
accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html";
+ revision "2016-03-15" {
+ description
+ "Updated to support multiple instances";
+ }
revision "2014-08-15" {
description
"Initial revision";
case data-change-counter-impl {
when "/config:modules/config:module/config:type = 'data-change-counter-impl'";
+ leaf counter-id {
+ type string;
+ }
+
leaf topology-name {
type string;
}
}
}
}
-}
\ No newline at end of file
+}
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev140815.DataChangeCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.DataChangeCounter;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.osgi.framework.BundleContext;
public class DataChangeCounterImplModuleTest extends AbstractConfigTest {
private static final String FACTORY_NAME = DataChangeCounterImplModuleFactory.NAME;
- private static final String INSTANCE_NAME = DataChangeCounterImplModuleFactory.SINGLETON_NAME;
+ private static final String INSTANCE_NAME = "data-change-counter";
private static final String DATA_BROKER_INSTANCE_NAME = "data-broker-instance";
+ private static final String COUNTER_ID = "counter";
+ private static final String NEW_COUNTER_ID = "new-counter";
private static final String TOPOLOGY_NAME = "test";
private static final String NEW_TOPOLOGY_NAME = "new-test";
@Test
public void testCreateBean() throws Exception {
- final CommitStatus status = createInstance(TOPOLOGY_NAME);
+ final CommitStatus status = createInstance(COUNTER_ID, TOPOLOGY_NAME);
assertBeanCount(1, FACTORY_NAME);
assertStatus(status, 2, 0, 0);
}
@Test
public void testReusingOldInstance() throws Exception {
- createInstance(TOPOLOGY_NAME);
+ createInstance(COUNTER_ID, TOPOLOGY_NAME);
final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
assertBeanCount(1, FACTORY_NAME);
final CommitStatus status = transaction.commit();
@Test
public void testReconfigureBean() throws Exception {
- createInstance(TOPOLOGY_NAME);
+ createInstance(COUNTER_ID, TOPOLOGY_NAME);
final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
final DataChangeCounterImplModuleMXBean mxBean = transaction.newMXBeanProxy(transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME),
DataChangeCounterImplModuleMXBean.class);
+ mxBean.setCounterId(NEW_COUNTER_ID);
mxBean.setTopologyName(NEW_TOPOLOGY_NAME);
final CommitStatus status = transaction.commit();
assertBeanCount(1, FACTORY_NAME);
final ConfigTransactionJMXClient transaction2 = this.configRegistryClient.createTransaction();
final DataChangeCounterImplModuleMXBean mxBean2 = transaction2.newMXBeanProxy(transaction2.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME),
DataChangeCounterImplModuleMXBean.class);
+ Assert.assertEquals(NEW_COUNTER_ID, mxBean2.getCounterId());
Assert.assertEquals(NEW_TOPOLOGY_NAME, mxBean2.getTopologyName());
}
- private CommitStatus createInstance(final String topologyName) throws Exception {
+ private CommitStatus createInstance(final String counterId, final String topologyName) throws Exception {
final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
final ObjectName on = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
final ObjectName dbOn = transaction.createModule(MockDataBrokerModuleFct.INSTANCE_NAME, DATA_BROKER_INSTANCE_NAME);
final DataChangeCounterImplModuleMXBean mxBean = transaction.newMXBeanProxy(on, DataChangeCounterImplModuleMXBean.class);
+ mxBean.setCounterId(counterId);
mxBean.setTopologyName(topologyName);
mxBean.setDataProvider(dbOn);
return transaction.commit();
import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev140815.DataChangeCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.DataChangeCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.data.change.counter.Counter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.data.change.counter.rev160315.data.change.counter.CounterKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public class TopologyDataChangeCounterTest extends AbstractDataBrokerTest {
+ private static final String COUNTER_ID1 = "counter1";
+ private static final String COUNTER_ID2 = "counter2";
+
@Test
public void testDataChangeCounter() throws InterruptedException, ExecutionException {
- final TopologyDataChangeCounter counter = new TopologyDataChangeCounter(getDataBroker());
- final Optional<Long> count = getCount();
+ final TopologyDataChangeCounter counter = new TopologyDataChangeCounter(getDataBroker(), COUNTER_ID1);
+ final Optional<Long> count = getCount(COUNTER_ID1);
assertTrue(count.isPresent());
assertEquals(0, count.get().longValue());
counter.onDataChanged(null);
- final Optional<Long> countAfterDataChange = getCount();
+ final Optional<Long> countAfterDataChange = getCount(COUNTER_ID1);
assertTrue(countAfterDataChange.isPresent());
assertEquals(1, countAfterDataChange.get().longValue());
counter.close();
- final Optional<Long> countAfterClose = getCount();
+ final Optional<Long> countAfterClose = getCount(COUNTER_ID1);
assertFalse(countAfterClose.isPresent());
}
- private Optional<Long> getCount() throws InterruptedException, ExecutionException {
+ @Test
+ public void testDataChangeCounterTwoInstances() throws InterruptedException, ExecutionException {
+ final TopologyDataChangeCounter counter1 = new TopologyDataChangeCounter(getDataBroker(), COUNTER_ID1);
+ final Optional<Long> count1 = getCount(COUNTER_ID1);
+ assertTrue(count1.isPresent());
+ assertEquals(0, count1.get().longValue());
+
+ final TopologyDataChangeCounter counter2 = new TopologyDataChangeCounter(getDataBroker(), COUNTER_ID2);
+ final Optional<Long> count2 = getCount(COUNTER_ID2);
+ assertTrue(count2.isPresent());
+ assertEquals(0, count2.get().longValue());
+
+ counter1.onDataChanged(null);
+ final Optional<Long> countAfterDataChange1 = getCount(COUNTER_ID1);
+ assertTrue(countAfterDataChange1.isPresent());
+ assertEquals(1, countAfterDataChange1.get().longValue());
+ // Check that counter2 does not get incremented
+ final Optional<Long> countAfterDataChange2 = getCount(COUNTER_ID2);
+ assertTrue(countAfterDataChange2.isPresent());
+ assertEquals(0, countAfterDataChange2.get().longValue());
+
+ counter1.close();
+ final Optional<Long> countAfterClose1 = getCount(COUNTER_ID1);
+ assertFalse(countAfterClose1.isPresent());
+ // Check that counter2 does not get deleted
+ final Optional<Long> countAfterClose2 = getCount(COUNTER_ID2);
+ assertTrue(countAfterClose2.isPresent());
+
+ counter2.close();
+ final Optional<Long> countAfterClose3 = getCount(COUNTER_ID2);
+ assertFalse(countAfterClose3.isPresent());
+ }
+
+ private Optional<Long> getCount(String counterId) throws InterruptedException, ExecutionException {
final ReadTransaction rTx = getDataBroker().newReadOnlyTransaction();
- final Optional<DataChangeCounter> dataMaybe = rTx.read(LogicalDatastoreType.OPERATIONAL, TopologyDataChangeCounter.IID).get();
+ final InstanceIdentifier<Counter> counterInstanceId = InstanceIdentifier.builder(DataChangeCounter.class)
+ .child(Counter.class, new CounterKey(counterId)).build();
+ final Optional<Counter> dataMaybe = rTx.read(LogicalDatastoreType.OPERATIONAL, counterInstanceId).get();
if (dataMaybe.isPresent()) {
return Optional.of(dataMaybe.get().getCount());
}