--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-data-change-counter</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- Copyright (c) 2014 Cisco Systems, Inc. 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 -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>commons.parent</artifactId>
+ <version>0.3.1-SNAPSHOT</version>
+ <relativePath>../commons/parent</relativePath>
+ </parent>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+ <artifactId>data-change-counter</artifactId>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-topology</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.config.yang.bgpcep.data.change.counter;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.protocol.data.change.counter.TopologyDataChangeCounter;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class DataChangeCounterImplModule extends org.opendaylight.controller.config.yang.bgpcep.data.change.counter.AbstractDataChangeCounterImplModule {
+
+ public DataChangeCounterImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public DataChangeCounterImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ org.opendaylight.controller.config.yang.bgpcep.data.change.counter.DataChangeCounterImplModule oldModule,
+ java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ JmxAttributeValidationException.checkNotNull(getTopologyName(), "value is not set.", topologyNameJmxAttribute);
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ final TopologyDataChangeCounter counter = new TopologyDataChangeCounter(getDataProviderDependency());
+ final InstanceIdentifier<Topology> topoIId = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(getTopologyName()))).toInstance();
+ final ListenerRegistration<DataChangeListener> registration = getDataProviderDependency().registerDataChangeListener(
+ LogicalDatastoreType.OPERATIONAL, topoIId, counter, DataBroker.DataChangeScope.SUBTREE);
+ return new DataChangeCounterCloseable(counter, registration);
+ }
+
+ private final class DataChangeCounterCloseable implements AutoCloseable {
+
+ private final TopologyDataChangeCounter inner;
+ private final ListenerRegistration<DataChangeListener> registration;
+
+ public DataChangeCounterCloseable(TopologyDataChangeCounter inner,
+ ListenerRegistration<DataChangeListener> registration) {
+ this.inner = inner;
+ this.registration = registration;
+ }
+
+ @Override
+ public void close() throws Exception {
+ this.registration.close();
+ this.inner.close();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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
+ */
+
+/*
+* Generated file
+*
+* Generated from: yang module name: odl-data-change-counter-cfg yang module local name: data-change-counter-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Aug 20 13:09:16 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+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);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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.protocol.data.change.counter;
+
+import java.util.concurrent.atomic.AtomicLong;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+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.rev140815.DataChangeCounterBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TopologyDataChangeCounter implements DataChangeListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TopologyDataChangeCounter.class);
+
+ protected static final InstanceIdentifier<DataChangeCounter> IID = InstanceIdentifier
+ .builder(DataChangeCounter.class).toInstance();
+
+ private final DataBroker dataBroker;
+ private AtomicLong count;
+
+ public TopologyDataChangeCounter(final DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ this.count = new AtomicLong(0);
+ putCount(this.count.get());
+ LOG.debug("Data change counter initiated");
+ }
+
+ @Override
+ public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ putCount(this.count.incrementAndGet());
+ LOG.debug("Data change #{}", this.count.get());
+ }
+
+ public void close() {
+ final WriteTransaction wTx = this.dataBroker.newWriteOnlyTransaction();
+ wTx.delete(LogicalDatastoreType.OPERATIONAL, IID);
+ wTx.submit();
+ LOG.debug("Data change counter removed");
+ }
+
+ private void putCount(final long count) {
+ final WriteTransaction wTx = this.dataBroker.newWriteOnlyTransaction();
+ wTx.put(LogicalDatastoreType.OPERATIONAL, IID, new DataChangeCounterBuilder().setCount(count)
+ .build());
+ wTx.submit();
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. 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
+-->
+<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>
+ </required-capabilities>
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <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>
+ <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>
+ </data-provider>
+ <topology-name>example-linkstate-topology</topology-name>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ </services>
+ </data>
+
+ </configuration>
+</snapshot>
--- /dev/null
+module data-change-counter {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:bgp-data-change-counter";
+ prefix "bgp-dcc";
+
+ organization "Cisco Systems, Inc.";
+ contact "Milos Fabian <milfabia@cisco.com>";
+
+ description
+ "This module contains the base data model of a topology
+ data-change counter. The module servers for testing purposes.
+
+ Copyright (c)2014 Cisco Systems, Inc. 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";
+
+ revision "2014-08-15" {
+ description
+ "Initial revision.";
+ }
+
+ container data-change-counter {
+ leaf count {
+ type uint32;
+ description
+ "The number of data changes.";
+ }
+ }
+ }
\ No newline at end of file
--- /dev/null
+// vi: set smarttab et sw=4 tabstop=4:
+module odl-data-change-counter-cfg {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:bgpcep:data:change:counter";
+ prefix "dcc-cfg";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+
+ organization "Cisco Systems, Inc.";
+
+ contact "Milos Fabian <milfabia@cisco.com>";
+
+ description
+ "This module contains the base YANG definitions for
+ topology data-change counter.
+
+ Copyright (c)2014 Cisco Systems, Inc. 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";
+
+ revision "2014-08-15" {
+ description
+ "Initial revision";
+ }
+
+ identity data-change-counter-impl {
+ base config:module-type;
+ config:java-name-prefix DataChangeCounterImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case data-change-counter-impl {
+ when "/config:modules/config:module/config:type = 'data-change-counter-impl'";
+
+ leaf topology-name {
+ type string;
+ }
+
+ container data-provider {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-async-data-broker;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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.protocol.data.change.counter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Optional;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+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;
+
+public class TopologyDataChangeCounterTest extends AbstractDataBrokerTest {
+
+ @Test
+ public void testDataChangeCounter() throws InterruptedException, ExecutionException {
+ final TopologyDataChangeCounter counter = new TopologyDataChangeCounter(getDataBroker());
+ final Optional<Long> count = getCount();
+ assertTrue(count.isPresent());
+ assertEquals(0, count.get().longValue());
+
+ counter.onDataChanged(null);
+ final Optional<Long> countAfterDataChange = getCount();
+ assertTrue(countAfterDataChange.isPresent());
+ assertEquals(1, countAfterDataChange.get().longValue());
+
+ counter.close();
+ final Optional<Long> countAfterClose = getCount();
+ assertFalse(countAfterClose.isPresent());
+ }
+
+ private Optional<Long> getCount() throws InterruptedException, ExecutionException {
+ final ReadTransaction rTx = getDataBroker().newReadOnlyTransaction();
+ final Optional<DataChangeCounter> dataMaybe = rTx.read(LogicalDatastoreType.OPERATIONAL, TopologyDataChangeCounter.IID).get();
+ if (dataMaybe.isPresent()) {
+ return Optional.of(dataMaybe.get().getCount());
+ }
+ return Optional.absent();
+ }
+}
<!-- Integration tests -->
<module>integration-tests</module>
+ <!--Test tools -->
+ <module>data-change-counter</module>
+
<!-- Parents -->
<module>commons/parent</module>
</modules>