From b495d88f63ba0b5b3959d7742ae683c869cf3ccc Mon Sep 17 00:00:00 2001 From: Vaclav Demcak Date: Wed, 17 Sep 2014 02:53:03 +0200 Subject: [PATCH] Bug 1484 - StatisticManager performance improvement refactoring * migration to new MD-SAL API (DataBroker DataChangeListener) * splitting project api/impl + (javaDoc for api) * clean pom.xml (xtend dependency and private-package, add sal-binding-broker-impl for test) * chaining req/resp StatisticNotification per FlowNode per statistic for prevent DS and RPC queue overload * add multipart msg joiner (StatManager wait for all relevant multipart msg for notification before write relevant Oper/DS action) - possibility to remove all not used subtrees (target -> reflect actual device contain asap for all alien node's data). * add FlowNode registratration - registration needs all SwitchFuture information for make a correct Stat target list (flows, groups, meters, queues, tables, nrOfTables, ports) - fix for sending not supported notifications to device * add logic for unique identification FlowId - DeviceFlow (create unique tweens FlowId and flowHash from responded device flow fields like match, priority, flowCookie, flowCookieMask) * change FlowCookieMap to FlowHashMap -> List * implement parallel statistics collecting for FlowCapableNode Sets * add MockTestSuite for a StatManager workflow interaction testing (neet to be fixed for newest changes) PASS tests https://jenkins.opendaylight.org/integration/job/integration-master-csit-base-of13 PASS tests https://jenkins.opendaylight.org/integration/job/integration-master-csit-karaf-l2switch-only/ PASS tests https://jenkins.opendaylight.org/integration/job/integration-master-csit-karaf-compatible-min/ Change-Id: I265b57378fc19573d6f18036825cb57f4131ca80 Signed-off-by: Jan Hajnar Signed-off-by: Vaclav Demcak --- opendaylight/karaf-branding/pom.xml | 62 +-- .../src/main/yang/flow-node-inventory.yang | 16 +- .../md-sal/statistics-manager/pom.xml | 6 +- .../AbstractListeningStatsTracker.java | 48 -- .../manager/AbstractStatsTracker.java | 127 ----- .../manager/FlowCapableContext.java | 27 - .../manager/FlowCapableTracker.java | 111 ---- .../md/statistics/manager/FlowStatsEntry.java | 64 --- .../statistics/manager/FlowStatsTracker.java | 313 ----------- .../manager/FlowTableStatsTracker.java | 82 --- .../manager/GroupDescStatsTracker.java | 123 ----- .../statistics/manager/GroupStatsTracker.java | 117 ---- .../manager/MeterConfigStatsTracker.java | 118 ---- .../statistics/manager/MeterStatsTracker.java | 124 ----- .../manager/MultipartMessageManager.java | 153 ------ .../manager/NodeConnectorStatsTracker.java | 95 ---- .../manager/NodeStatisticsHandler.java | 333 ----------- .../statistics/manager/QueueStatsEntry.java | 62 --- .../statistics/manager/QueueStatsTracker.java | 161 ------ .../manager/StatListeningCommiter.java | 34 ++ .../manager/StatNodeRegistration.java | 50 ++ .../manager/StatNotifyCommiter.java | 31 ++ .../statistics/manager/StatPermCollector.java | 115 ++++ .../statistics/manager/StatRpcMsgManager.java | 191 +++++++ .../manager/StatisticsListener.java | 144 ----- .../statistics/manager/StatisticsManager.java | 179 ++++++ .../manager/StatisticsManagerActivator.java | 55 +- .../manager/StatisticsProvider.java | 172 ------ .../manager/StatisticsRequestScheduler.java | 140 ----- .../impl/StatAbstractListenCommit.java | 134 +++++ .../impl/StatAbstractNotifyCommit.java | 134 +++++ .../manager/impl/StatListenCommitFlow.java | 451 +++++++++++++++ .../manager/impl/StatListenCommitGroup.java | 296 ++++++++++ .../manager/impl/StatListenCommitMeter.java | 283 ++++++++++ .../manager/impl/StatListenCommitQueue.java | 149 +++++ .../impl/StatNodeRegistrationImpl.java | 207 +++++++ .../manager/impl/StatNotifyCommitPort.java | 148 +++++ .../manager/impl/StatNotifyCommitTable.java | 138 +++++ .../manager/impl/StatPermCollectorImpl.java | 305 +++++++++++ .../StatRPCFailedException.java} | 10 +- .../manager/impl/StatRpcMsgManagerImpl.java | 517 ++++++++++++++++++ .../manager/impl/StatisticsManagerImpl.java | 358 ++++++++++++ .../{ => impl/helper}/FlowComparator.java | 82 ++- .../manager/StatisticsManagerProvider.java | 39 ++ .../helper}/StatisticsUpdateCommiterTest.java | 44 +- .../java/test/mock/FlowStatisticsTest.java | 159 ++++++ .../java/test/mock/GroupStatisticsTest.java | 151 +++++ .../java/test/mock/MeterStatisticsTest.java | 150 +++++ .../java/test/mock/NodeRegistrationTest.java | 48 ++ .../java/test/mock/PortStatisticsTest.java | 73 +++ .../java/test/mock/QueueStatisticsTest.java | 197 +++++++ .../java/test/mock/TableStatisticsTest.java | 71 +++ .../mock/util/AbstractDataBrokerTest.java | 60 ++ .../mock/util/AbstractSchemaAwareTest.java | 44 ++ .../test/mock/util/BundleContextMock.java | 149 +++++ .../mock/util/DataBrokerTestCustomizer.java | 111 ++++ .../test/mock/util/FlowMockGenerator.java | 30 + .../test/mock/util/GroupMockGenerator.java | 23 + .../test/mock/util/MatchMockGenerator.java | 30 + .../test/mock/util/MeterMockGenerator.java | 35 ++ .../test/mock/util/MockSchemaService.java | 62 +++ .../NotificationProviderServiceHelper.java | 29 + ...OpendaylightFlowStatisticsServiceMock.java | 116 ++++ ...aylightFlowTableStatisticsServiceMock.java | 57 ++ ...pendaylightGroupStatisticsServiceMock.java | 123 +++++ ...pendaylightMeterStatisticsServiceMock.java | 119 ++++ ...OpendaylightPortStatisticsServiceMock.java | 67 +++ ...pendaylightQueueStatisticsServiceMock.java | 83 +++ .../test/mock/util/PortMockGenerator.java | 23 + .../test/mock/util/ProviderContextMock.java | 69 +++ .../test/mock/util/QueueMockGenerator.java | 27 + .../mock/util/RpcProviderRegistryMock.java | 93 ++++ .../test/mock/util/StatisticsManagerTest.java | 198 +++++++ .../test/java/test/mock/util/TestUtils.java | 11 + 74 files changed, 6322 insertions(+), 2634 deletions(-) delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableContext.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsEntry.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatListeningCommiter.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNodeRegistration.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNotifyCommiter.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatPermCollector.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatRpcMsgManager.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsListener.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java delete mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractListenCommit.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractNotifyCommit.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitFlow.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitGroup.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitMeter.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNodeRegistrationImpl.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitPort.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitTable.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatPermCollectorImpl.java rename opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/{RPCFailedException.java => impl/StatRPCFailedException.java} (75%) create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatRpcMsgManagerImpl.java create mode 100644 opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java rename opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/{ => impl/helper}/FlowComparator.java (80%) create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java rename opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/{ => impl/helper}/StatisticsUpdateCommiterTest.java (81%) create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/BundleContextMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/FlowMockGenerator.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/GroupMockGenerator.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MatchMockGenerator.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MeterMockGenerator.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MockSchemaService.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/NotificationProviderServiceHelper.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/PortMockGenerator.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/QueueMockGenerator.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java create mode 100644 opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java diff --git a/opendaylight/karaf-branding/pom.xml b/opendaylight/karaf-branding/pom.xml index 444e77057a..722bdeaa8d 100644 --- a/opendaylight/karaf-branding/pom.xml +++ b/opendaylight/karaf-branding/pom.xml @@ -1,39 +1,37 @@ - 4.0.0 - - org.opendaylight.controller - releasepom - 0.1.2-SNAPSHOT - ../.. - + 4.0.0 + org.opendaylight.controller - karaf.branding - 1.0.0-SNAPSHOT - bundle - OpenDaylight :: Karaf :: Branding + releasepom + 0.1.2-SNAPSHOT + ../.. + + org.opendaylight.controller + karaf.branding + 1.0.0-SNAPSHOT + bundle + OpenDaylight :: Karaf :: Branding - - - - org.apache.felix - maven-bundle-plugin - 2.4.0 - true - - - ${project.artifactId} - * - !* - - org.apache.karaf.branding - - *;public-context:=false - - - - - + + + + org.apache.felix + maven-bundle-plugin + 2.4.0 + true + + + ${project.artifactId} + * + !* + org.apache.karaf.branding + *;public-context:=false + + + + + diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang index 5a40022963..fc0eb4cf72 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang @@ -236,13 +236,17 @@ module flow-node-inventory { } augment "/inv:nodes/inv:node/table" { - ext:augment-identifier "flow-cookie-mapping"; - list flow-cookie-map { - key "cookie"; - leaf cookie { - type flow:flow-cookie; + ext:augment-identifier "flow-hash-id-mapping"; + description "Flow is identified by match and priority on device. So Operational/DS + has to simulate that behavior and contract between FlowId and match+priority + identification should represent Flow hashCode. Flow has to contain only + match priority and flowCookie for create a hashCode"; + list flow-hash-id-map { + key "hash"; + leaf hash { + type string; } - leaf-list flow-ids { + leaf flow-id { type flow-id; } } diff --git a/opendaylight/md-sal/statistics-manager/pom.xml b/opendaylight/md-sal/statistics-manager/pom.xml index 399d53b67f..5b8c6268e2 100644 --- a/opendaylight/md-sal/statistics-manager/pom.xml +++ b/opendaylight/md-sal/statistics-manager/pom.xml @@ -21,8 +21,9 @@ junit - org.eclipse.xtend - org.eclipse.xtend.lib + org.opendaylight.controller + sal-binding-broker-impl + test org.opendaylight.controller @@ -57,7 +58,6 @@ org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator - org.opendaylight.controller.md.statistics.manager diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java deleted file mode 100644 index 167fb21ffd..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.md.statistics.manager; - -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; - -abstract class AbstractListeningStatsTracker extends AbstractStatsTracker implements AutoCloseable, DataChangeListener { - private static final Logger logger = LoggerFactory.getLogger(AbstractListeningStatsTracker.class); - private ListenerRegistration reg; - - protected AbstractListeningStatsTracker(FlowCapableContext context) { - super(context); - } - - protected abstract InstanceIdentifier listenPath(); - protected abstract String statName(); - - public void start(final DataBrokerService dbs) { - Preconditions.checkState(reg == null); - - reg = dbs.registerDataChangeListener(listenPath(), this); - logger.debug("{} Statistics tracker for node {} started", statName(), getNodeIdentifier()); - } - - @Override - public final void close() { - if (reg != null) { - try { - reg.close(); - } catch (Exception e) { - logger.warn("Failed to stop {} Statistics tracker for node {}", statName(), getNodeIdentifier(), e); - } - reg = null; - } - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java deleted file mode 100644 index 838aeb7dc3..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.Future; - -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.JdkFutureAdapters; - -abstract class AbstractStatsTracker { - private static final Logger logger = LoggerFactory.getLogger(AbstractStatsTracker.class); - - private static final int WAIT_FOR_REQUEST_CYCLE = 2; - - private final FutureCallback> callback = - new FutureCallback>() { - @Override - public void onSuccess(RpcResult result) { - if (result.isSuccessful()) { - final TransactionId id = result.getResult().getTransactionId(); - if (id == null) { - final Throwable t = new UnsupportedOperationException("No protocol support"); - t.fillInStackTrace(); - onFailure(t); - } else { - context.registerTransaction(id); - } - } else { - logger.debug("Statistics request failed: {}", result.getErrors()); - - final Throwable t = new RPCFailedException("Failed to send statistics request", result.getErrors()); - t.fillInStackTrace(); - onFailure(t); - } - } - - @Override - public void onFailure(Throwable t) { - logger.debug("Failed to send statistics request", t); - } - }; - - private final Map trackedItems = new HashMap<>(); - private final FlowCapableContext context; - private long requestCounter; - - protected AbstractStatsTracker(final FlowCapableContext context) { - this.context = Preconditions.checkNotNull(context); - this.requestCounter = 0; - } - - protected final InstanceIdentifierBuilder getNodeIdentifierBuilder() { - return getNodeIdentifier().builder(); - } - - protected final NodeRef getNodeRef() { - return context.getNodeRef(); - } - - protected final InstanceIdentifier getNodeIdentifier() { - return context.getNodeIdentifier(); - } - - protected final void requestHelper(Future> future) { - Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), callback); - } - - protected final DataModificationTransaction startTransaction() { - return context.startDataModification(); - } - - public final synchronized void increaseRequestCounter(){ - this.requestCounter++; - } - protected abstract void cleanupSingleStat(DataModificationTransaction trans, K item); - protected abstract K updateSingleStat(DataModificationTransaction trans, I item); - protected abstract K createInvariantKey(K item); - public abstract void request(); - - public final synchronized void updateStats(List list) { - - final DataModificationTransaction trans = startTransaction(); - for (final I item : list) { - K key = updateSingleStat(trans, item); - trackedItems.put(createInvariantKey(key), requestCounter); - } - - trans.commit(); - } - - /** - * Statistics will be cleaned up if not update in last two request cycles. - * @param trans - */ - public final synchronized void cleanup(final DataModificationTransaction trans) { - for (Iterator> it = trackedItems.entrySet().iterator();it.hasNext();){ - Entry e = it.next(); - if (requestCounter >= e.getValue()+WAIT_FOR_REQUEST_CYCLE) { - cleanupSingleStat(trans, e.getKey()); - it.remove(); - } - } - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableContext.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableContext.java deleted file mode 100644 index 520b344199..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableContext.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.md.statistics.manager; - -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -/** - * Interface exposed to AbstractStatsTracker by its parent NodeStatisticsHandler. - * While we could simply exist without this interface, its purpose is to document - * the contract between the two classes. - */ -interface FlowCapableContext { - InstanceIdentifier getNodeIdentifier(); - NodeRef getNodeRef(); - DataModificationTransaction startDataModification(); - void registerTransaction(TransactionId id); - void registerTableTransaction(TransactionId id, Short tableId); -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableTracker.java deleted file mode 100644 index bb1544c57a..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableTracker.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.Collection; - -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Function; -import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.Collections2; -import com.google.common.collect.Sets; - -/** - * There is a single instance of this class and that instance is responsible for - * monitoring the operational data store for nodes being created/deleted and - * notifying StatisticsProvider. These events then control the lifecycle of - * NodeStatisticsHandler for a particular switch. - */ -final class FlowCapableTracker implements DataChangeListener { - private static final Logger logger = LoggerFactory.getLogger(FlowCapableTracker.class); - - private final InstanceIdentifier root; - private final StatisticsProvider stats; - - private final Predicate> filterIdentifiers = new Predicate>() { - @Override - public boolean apply(final InstanceIdentifier input) { - /* - * This notification has been triggered either by the ancestor, - * descendant or directly for the FlowCapableNode itself. We - * are not interested descendants, so let's prune them based - * on the depth of their identifier. - */ - if (root.getPath().size() < input.getPath().size()) { - logger.debug("Ignoring notification for descendant {}", input); - return false; - } - - logger.debug("Including notification for {}", input); - return true; - } - }; - - public FlowCapableTracker(final StatisticsProvider stats, InstanceIdentifier root) { - this.stats = Preconditions.checkNotNull(stats); - this.root = Preconditions.checkNotNull(root); - } - - /* - * This method is synchronized because we want to make sure to serialize input - * from the datastore. Competing add/remove could be problematic otherwise. - */ - @Override - public synchronized void onDataChanged(final DataChangeEvent, DataObject> change) { - logger.debug("Tracker at root {} processing notification", root); - - /* - * First process all the identifiers which were removed, trying to figure out - * whether they constitute removal of FlowCapableNode. - */ - final Collection removedNodes = - Collections2.filter(Collections2.transform( - Sets.filter(change.getRemovedOperationalData(), filterIdentifiers), - new Function, NodeKey>() { - @Override - public NodeKey apply(final InstanceIdentifier input) { - final NodeKey key = input.firstKeyOf(Node.class, NodeKey.class); - if (key == null) { - // FIXME: do we have a backup plan? - logger.info("Failed to extract node key from {}", input); - } - return key; - } - }), Predicates.notNull()); - stats.stopNodeHandlers(removedNodes); - - final Collection addedNodes = - Collections2.filter(Collections2.transform( - Sets.filter(change.getCreatedOperationalData().keySet(), filterIdentifiers), - new Function, NodeKey>() { - @Override - public NodeKey apply(final InstanceIdentifier input) { - final NodeKey key = input.firstKeyOf(Node.class, NodeKey.class); - if (key == null) { - // FIXME: do we have a backup plan? - logger.info("Failed to extract node key from {}", input); - } - return key; - } - }), Predicates.notNull()); - stats.startNodeHandlers(addedNodes); - - logger.debug("Tracker at root {} finished processing notification", root); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java deleted file mode 100644 index c43c1ebaca..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; - -final class FlowStatsEntry { - private final Short tableId; - private final Flow flow; - - public FlowStatsEntry(Short tableId, Flow flow){ - this.tableId = tableId; - this.flow = flow; - } - - public Short getTableId() { - return tableId; - } - - public Flow getFlow() { - return flow; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((flow == null) ? 0 : flow.hashCode()); - result = prime * result + ((tableId == null) ? 0 : tableId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - FlowStatsEntry other = (FlowStatsEntry) obj; - if (flow == null) { - if (other.flow != null) - return false; - } else if (!flow.equals(other.flow)) - return false; - if (tableId == null) { - if (other.tableId != null) - return false; - } else if (!tableId.equals(other.tableId)) - return false; - return true; - } - - @Override - public String toString() { - return "FlowStatsEntry [tableId=" + tableId + ", flow=" + flow + "]"; - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java deleted file mode 100644 index d540f115c3..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.math.BigInteger; -import java.util.Collection; -import java.util.Collections; -import java.util.Map.Entry; - -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCookieMapping; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowCookieMap; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowCookieMapBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowCookieMapKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Optional; - -final class FlowStatsTracker extends AbstractListeningStatsTracker { - private static final Logger LOG = LoggerFactory.getLogger(FlowStatsTracker.class); - private static final String ALIEN_SYSTEM_FLOW_ID = "#UF$TABLE*"; - private final OpendaylightFlowStatisticsService flowStatsService; - private FlowTableStatsTracker flowTableStats; - private int unaccountedFlowsCounter = 1; - - - FlowStatsTracker(final OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context) { - super(context); - this.flowStatsService = flowStatsService; - } - FlowStatsTracker(final OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, final FlowTableStatsTracker flowTableStats) { - this(flowStatsService, context); - this.flowTableStats = flowTableStats; - } - - @Override - protected void cleanupSingleStat(final DataModificationTransaction trans, final FlowStatsEntry item) { - KeyedInstanceIdentifier flowRef = getNodeIdentifier() - .augmentation(FlowCapableNode.class) - .child(Table.class, new TableKey(item.getTableId())) - .child(Flow.class, item.getFlow().getKey()); - trans.removeOperationalData(flowRef); - } - - @Override - protected FlowStatsEntry updateSingleStat(final DataModificationTransaction trans, final FlowAndStatisticsMapList map) { - short tableId = map.getTableId(); - - FlowStatisticsDataBuilder flowStatisticsData = new FlowStatisticsDataBuilder(); - - FlowBuilder flowBuilder = new FlowBuilder(map); - if (map.getFlowId() != null) { - flowBuilder.setId(new FlowId(map.getFlowId().getValue())); - } - if (map.getFlowId() != null) { - flowBuilder.setKey(new FlowKey(new FlowId(map.getKey().getFlowId().getValue()))); - } - - Flow flowRule = flowBuilder.build(); - - FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder(); - stats.setByteCount(map.getByteCount()); - stats.setPacketCount(map.getPacketCount()); - stats.setDuration(map.getDuration()); - - GenericStatistics flowStats = stats.build(); - - //Augment the data to the flow node - - FlowStatisticsBuilder flowStatistics = new FlowStatisticsBuilder(); - flowStatistics.setByteCount(flowStats.getByteCount()); - flowStatistics.setPacketCount(flowStats.getPacketCount()); - flowStatistics.setDuration(flowStats.getDuration()); - - flowStatisticsData.setFlowStatistics(flowStatistics.build()); - - LOG.debug("Flow : {}",flowRule.toString()); - LOG.debug("Statistics to augment : {}",flowStatistics.build().toString()); - - InstanceIdentifier tableRef = getNodeIdentifierBuilder() - .augmentation(FlowCapableNode.class) - .child(Table.class, new TableKey(tableId)).toInstance(); - - final FlowCookie flowCookie = flowRule.getCookie() != null - ? flowRule.getCookie() : new FlowCookie(BigInteger.ZERO); - final InstanceIdentifier flowCookieRef = tableRef - .augmentation(FlowCookieMapping.class) - .child(FlowCookieMap.class, new FlowCookieMapKey(flowCookie)); - - FlowCookieMap cookieMap = (FlowCookieMap) trans.readOperationalData(flowCookieRef); - - /* find flowKey in FlowCookieMap from DataStore/OPERATIONAL */ - Optional flowKey = this.getExistFlowKey(flowRule, tableRef, trans, cookieMap); - if ( ! flowKey.isPresent()) { - /* DataStore/CONFIG For every first statistic needs to be created */ - flowKey = this.getFlowKeyFromExistFlow(flowRule, tableRef, trans); - if ( ! flowKey.isPresent()) { - /* Alien flow */ - flowKey = this.makeAlienFlowKey(flowRule); - } - cookieMap = applyNewFlowKey(cookieMap, flowKey, flowCookie); - trans.putOperationalData(flowCookieRef, cookieMap); - } - - InstanceIdentifier flowRef = getNodeIdentifierBuilder() - .augmentation(FlowCapableNode.class) - .child(Table.class, new TableKey(tableId)) - .child(Flow.class, flowKey.get()).toInstance(); - flowBuilder.setKey(flowKey.get()); - flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build()); - - // Update entry with timestamp of latest response - flowBuilder.setKey(flowKey.get()); - FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId, flowBuilder.build()); - trans.putOperationalData(flowRef, flowBuilder.build()); - return flowStatsEntry; - } - - @Override - protected InstanceIdentifier listenPath() { - return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class).build(); - } - - @Override - protected String statName() { - return "Flow"; - } - - @Override - public void request() { - // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest() - // comes back -- we do not have any tables anyway. - final Collection tables = flowTableStats.getTables(); - LOG.debug("Node {} supports {} table(s)", this.getNodeRef(), tables.size()); - for (final TableKey key : tables) { - LOG.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), this.getNodeRef()); - this.requestAggregateFlows(key); - } - - this.requestAllFlowsAllTables(); - - } - public void requestAllFlowsAllTables() { - if (flowStatsService != null) { - final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(flowStatsService.getAllFlowsStatisticsFromAllFlowTables(input.build())); - } - } - - public void requestAggregateFlows(final TableKey key) { - if (flowStatsService != null) { - GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder input = - new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder(); - - input.setNode(getNodeRef()); - input.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(key.getId())); - requestHelper(flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build())); - } - } - - public void requestFlow(final Flow flow) { - if (flowStatsService != null) { - final GetFlowStatisticsFromFlowTableInputBuilder input = - new GetFlowStatisticsFromFlowTableInputBuilder(flow); - input.setNode(getNodeRef()); - - requestHelper(flowStatsService.getFlowStatisticsFromFlowTable(input.build())); - } - } - - @Override - public void onDataChanged(final DataChangeEvent, DataObject> change) { - for (Entry, DataObject> e : change.getCreatedConfigurationData().entrySet()) { - if (Flow.class.equals(e.getKey().getTargetType())) { - final Flow flow = (Flow) e.getValue(); - LOG.debug("Key {} triggered request for flow {}", e.getKey(), flow); - requestFlow(flow); - } else { - LOG.debug("Ignoring key {}", e.getKey()); - } - } - - final DataModificationTransaction trans = startTransaction(); - for (InstanceIdentifier key : change.getRemovedConfigurationData()) { - if (Flow.class.equals(key.getTargetType())) { - @SuppressWarnings("unchecked") - final InstanceIdentifier flow = (InstanceIdentifier)key; - LOG.debug("Key {} triggered remove of Flow from operational space.", key); - trans.removeOperationalData(flow); - } - } - trans.commit(); - } - - @Override - public void start(final DataBrokerService dbs) { - if (flowStatsService == null) { - LOG.debug("No Flow Statistics service, not subscribing to flows on node {}", getNodeIdentifier()); - return; - } - - super.start(dbs); - } - - /* Returns Exist FlowKey from exist FlowCookieMap identified by cookie - * and by switch flow identification (priority and match)*/ - private Optional getExistFlowKey(final Flow flowRule, final InstanceIdentifier
tableRef, - final DataModificationTransaction trans, final FlowCookieMap cookieMap) { - - if (cookieMap != null) { - for (FlowId flowId : cookieMap.getFlowIds()) { - InstanceIdentifier flowIdent = tableRef.child(Flow.class, new FlowKey(flowId)); - if (flowId.getValue().startsWith(ALIEN_SYSTEM_FLOW_ID)) { - LOG.debug("Search for flow in the operational datastore by flowID: {} ", flowIdent); - Flow readedFlow = (Flow) trans.readOperationalData(flowIdent); - if (FlowComparator.flowEquals(flowRule, readedFlow)) { - return Optional. of(new FlowKey(flowId)); - } - } else { - LOG.debug("Search for flow in the configuration datastore by flowID: {} ", flowIdent); - Flow readedFlow = (Flow) trans.readConfigurationData(flowIdent); - if (FlowComparator.flowEquals(flowRule, readedFlow)) { - return Optional. of(new FlowKey(flowId)); - } - } - } - LOG.debug("Flow was not found in the datastore. Flow {} ", flowRule); - } - return Optional.absent(); - } - - /* Returns FlowKey from existing Flow in DataStore/CONFIGURATIONAL which is identified by cookie - * and by switch flow identification (priority and match) */ - private Optional getFlowKeyFromExistFlow(final Flow flowRule, final InstanceIdentifier
tableRef, - final DataModificationTransaction trans) { - - /* Try to find it in DataSotre/CONFIG */ - Table table= (Table)trans.readConfigurationData(tableRef); - if(table != null) { - for(Flow existingFlow : table.getFlow()) { - LOG.debug("Existing flow in data store : {}",existingFlow.toString()); - if(FlowComparator.flowEquals(flowRule,existingFlow)){ - return Optional. of(new FlowKey(existingFlow.getId())); - } - } - } - return Optional.absent(); - } - - /* Returns FlowKey which doesn't exist in any DataStore for now */ - private Optional makeAlienFlowKey(final Flow flowRule) { - - StringBuilder sBuilder = new StringBuilder(ALIEN_SYSTEM_FLOW_ID) - .append(flowRule.getTableId()).append("-").append(this.unaccountedFlowsCounter); - this.unaccountedFlowsCounter++; - final FlowId flowId = new FlowId(sBuilder.toString()); - return Optional. of(new FlowKey(flowId)); - } - - /* Build new whole FlowCookieMap or add new flowKey */ - private FlowCookieMap applyNewFlowKey(FlowCookieMap flowCookieMap, final Optional flowKey, - final FlowCookie flowCookie) { - if (flowCookieMap != null) { - flowCookieMap.getFlowIds().add(flowKey.get().getId()); - } else { - final FlowCookieMapBuilder flowCookieMapBuilder = new FlowCookieMapBuilder(); - flowCookieMapBuilder.setCookie(flowCookie); - flowCookieMapBuilder.setFlowIds(Collections.singletonList(flowKey.get().getId())); - flowCookieMap = flowCookieMapBuilder.build(); - } - return flowCookieMap; - } - - @Override - protected FlowStatsEntry createInvariantKey(final FlowStatsEntry item) { - FlowBuilder newFlow = new FlowBuilder(); - newFlow.setId(item.getFlow().getId()); - newFlow.setKey(item.getFlow().getKey()); - newFlow.fieldsFrom(item.getFlow()); - return new FlowStatsEntry(item.getTableId(),newFlow.build()); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java deleted file mode 100644 index 2e85058041..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ConcurrentSkipListSet; - -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsDataBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -final class FlowTableStatsTracker extends AbstractStatsTracker { - private final Set privateTables = new ConcurrentSkipListSet<>(); - private final Set tables = Collections.unmodifiableSet(privateTables); - private final OpendaylightFlowTableStatisticsService flowTableStatsService; - - FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context) { - super(context); - this.flowTableStatsService = flowTableStatsService; - } - - Set getTables() { - return tables; - } - - @Override - protected void cleanupSingleStat(DataModificationTransaction trans, FlowTableAndStatisticsMap item) { - // TODO: do we want to do this? - } - - @Override - protected FlowTableAndStatisticsMap updateSingleStat(DataModificationTransaction trans, FlowTableAndStatisticsMap item) { - - InstanceIdentifier
tableRef = getNodeIdentifierBuilder() - .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(item.getTableId().getValue())).build(); - - FlowTableStatisticsDataBuilder statisticsDataBuilder = new FlowTableStatisticsDataBuilder(); - final FlowTableStatistics stats = new FlowTableStatisticsBuilder(item).build(); - statisticsDataBuilder.setFlowTableStatistics(stats); - - TableBuilder tableBuilder = new TableBuilder(); - tableBuilder.setKey(new TableKey(item.getTableId().getValue())); - tableBuilder.addAugmentation(FlowTableStatisticsData.class, statisticsDataBuilder.build()); - trans.putOperationalData(tableRef, tableBuilder.build()); - return item; - } - - @Override - public void request() { - if (flowTableStatsService != null) { - final GetFlowTablesStatisticsInputBuilder input = new GetFlowTablesStatisticsInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(flowTableStatsService.getFlowTablesStatistics(input.build())); - } - } - - @Override - protected FlowTableAndStatisticsMap createInvariantKey(FlowTableAndStatisticsMap item) { - FlowTableAndStatisticsMapBuilder flowTableAndStatisticsMapBuilder = new FlowTableAndStatisticsMapBuilder(); - flowTableAndStatisticsMapBuilder.setTableId(item.getTableId()); - flowTableAndStatisticsMapBuilder.setKey(item.getKey()); - return flowTableAndStatisticsMapBuilder.build(); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java deleted file mode 100644 index 11c6d4c22d..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStatsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.desc.GroupDescBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class GroupDescStatsTracker extends AbstractListeningStatsTracker { - private static final Logger logger = LoggerFactory.getLogger(GroupDescStatsTracker.class); - private final OpendaylightGroupStatisticsService groupStatsService; - - public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context) { - super(context); - this.groupStatsService = groupStatsService; - } - - @Override - protected GroupDescStats updateSingleStat(DataModificationTransaction trans, GroupDescStats item) { - GroupBuilder groupBuilder = new GroupBuilder(); - GroupKey groupKey = new GroupKey(item.getGroupId()); - groupBuilder.setKey(groupKey); - - InstanceIdentifier groupRef = getNodeIdentifierBuilder() - .augmentation(FlowCapableNode.class).child(Group.class,groupKey).build(); - - NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder(); - groupDesc.setGroupDesc(new GroupDescBuilder(item).build()); - - //Update augmented data - groupBuilder.addAugmentation(NodeGroupDescStats.class, groupDesc.build()); - - trans.putOperationalData(groupRef, groupBuilder.build()); - return item; - } - - @Override - protected void cleanupSingleStat(DataModificationTransaction trans, GroupDescStats item) { - InstanceIdentifier groupRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class) - .child(Group.class, new GroupKey(item.getGroupId())).augmentation(NodeGroupDescStats.class).build(); - trans.removeOperationalData(groupRef); - } - - @Override - protected InstanceIdentifier listenPath() { - return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Group.class).build(); - } - - @Override - protected String statName() { - return "Group Descriptor"; - } - - @Override - public void request() { - if (groupStatsService != null) { - final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(groupStatsService.getGroupDescription(input.build())); - } - } - - @Override - public void onDataChanged(DataChangeEvent, DataObject> change) { - for (InstanceIdentifier key : change.getCreatedConfigurationData().keySet()) { - if (Group.class.equals(key.getTargetType())) { - logger.debug("Key {} triggered request", key); - request(); - } else { - logger.debug("Ignoring key {}", key); - } - } - - final DataModificationTransaction trans = startTransaction(); - for (InstanceIdentifier key : change.getRemovedConfigurationData()) { - if (Group.class.equals(key.getTargetType())) { - @SuppressWarnings("unchecked") - InstanceIdentifier group = (InstanceIdentifier)key; - InstanceIdentifier del = group.augmentation(NodeGroupDescStats.class); - logger.debug("Key {} triggered remove of augmentation {}", key, del); - - trans.removeOperationalData(del); - } - } - trans.commit(); - } - - @Override - public void start(final DataBrokerService dbs) { - if (groupStatsService == null) { - logger.debug("No Group Statistics service, not subscribing to groups on node {}", getNodeIdentifier()); - return; - } - - super.start(dbs); - } - - @Override - protected GroupDescStats createInvariantKey(GroupDescStats item) { - // No invariant data exist in the group description stats. - return item; - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java deleted file mode 100644 index f3ba45643c..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStatsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; - -final class GroupStatsTracker extends AbstractListeningStatsTracker { - private static final Logger logger = LoggerFactory.getLogger(GroupStatsTracker.class); - private final OpendaylightGroupStatisticsService groupStatsService; - - GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context) { - super(context); - this.groupStatsService = Preconditions.checkNotNull(groupStatsService); - } - - @Override - protected void cleanupSingleStat(DataModificationTransaction trans, GroupStats item) { - InstanceIdentifier groupRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class) - .child(Group.class, new GroupKey(item.getGroupId())).augmentation(NodeGroupStatistics.class).build(); - trans.removeOperationalData(groupRef); - } - - @Override - protected GroupStats updateSingleStat(DataModificationTransaction trans, - GroupStats item) { - GroupBuilder groupBuilder = new GroupBuilder(); - GroupKey groupKey = new GroupKey(item.getGroupId()); - groupBuilder.setKey(groupKey); - - InstanceIdentifier groupRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class) - .child(Group.class,groupKey).build(); - - NodeGroupStatisticsBuilder groupStatisticsBuilder= new NodeGroupStatisticsBuilder(); - groupStatisticsBuilder.setGroupStatistics(new GroupStatisticsBuilder(item).build()); - - //Update augmented data - groupBuilder.addAugmentation(NodeGroupStatistics.class, groupStatisticsBuilder.build()); - trans.putOperationalData(groupRef, groupBuilder.build()); - return item; - } - - @Override - protected InstanceIdentifier listenPath() { - return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Group.class).build(); - } - - @Override - protected String statName() { - return "Group"; - } - - @Override - public void request() { - final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(groupStatsService.getAllGroupStatistics(input.build())); - } - - @Override - public void onDataChanged(DataChangeEvent, DataObject> change) { - final DataModificationTransaction trans = startTransaction(); - for (InstanceIdentifier key : change.getRemovedConfigurationData()) { - if (Group.class.equals(key.getTargetType())) { - @SuppressWarnings("unchecked") - InstanceIdentifier group = (InstanceIdentifier)key; - InstanceIdentifier del = group.augmentation(NodeGroupStatistics.class); - logger.debug("Key {} triggered remove of augmentation {}", key, del); - - trans.removeOperationalData(del); - } - } - trans.commit(); - } - - @Override - public void start(final DataBrokerService dbs) { - if (groupStatsService == null) { - logger.debug("No Group Statistics service, not subscribing to groups on node {}", getNodeIdentifier()); - return; - } - - super.start(dbs); - } - - @Override - protected GroupStats createInvariantKey(GroupStats item) { - GroupStatsBuilder groupStatsBuilder = new GroupStatsBuilder(); - groupStatsBuilder.setKey(item.getKey()); - groupStatsBuilder.setGroupId(item.getGroupId()); - return groupStatsBuilder.build(); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java deleted file mode 100644 index 88139fc606..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStatsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterConfigStatsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class MeterConfigStatsTracker extends AbstractListeningStatsTracker { - private static final Logger logger = LoggerFactory.getLogger(MeterConfigStatsTracker.class); - private final OpendaylightMeterStatisticsService meterStatsService; - - protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) { - super(context); - this.meterStatsService = meterStatsService; - } - - @Override - protected void cleanupSingleStat(DataModificationTransaction trans, MeterConfigStats item) { - InstanceIdentifier meterRef = getNodeIdentifierBuilder() - .augmentation(FlowCapableNode.class) - .child(Meter.class, new MeterKey(item.getMeterId())) - .augmentation(NodeMeterConfigStats.class).build(); - trans.removeOperationalData(meterRef); - } - - @Override - protected MeterConfigStats updateSingleStat(DataModificationTransaction trans, MeterConfigStats item) { - MeterBuilder meterBuilder = new MeterBuilder(); - MeterKey meterKey = new MeterKey(item.getMeterId()); - meterBuilder.setKey(meterKey); - - InstanceIdentifier meterRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class) - .child(Meter.class,meterKey).toInstance(); - - NodeMeterConfigStatsBuilder meterConfig = new NodeMeterConfigStatsBuilder(); - meterConfig.setMeterConfigStats(new MeterConfigStatsBuilder(item).build()); - - //Update augmented data - meterBuilder.addAugmentation(NodeMeterConfigStats.class, meterConfig.build()); - - trans.putOperationalData(meterRef, meterBuilder.build()); - return item; - } - - @Override - public void request() { - if (meterStatsService != null) { - GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(meterStatsService.getAllMeterConfigStatistics(input.build())); - } - } - - @Override - public void onDataChanged(DataChangeEvent, DataObject> change) { - final DataModificationTransaction trans = startTransaction(); - - for (InstanceIdentifier key : change.getRemovedConfigurationData()) { - if (Meter.class.equals(key.getTargetType())) { - @SuppressWarnings("unchecked") - InstanceIdentifier meter = (InstanceIdentifier)key; - - InstanceIdentifier nodeMeterStatisticsAugmentation = - meter.augmentation(NodeMeterConfigStats.class); - trans.removeOperationalData(nodeMeterStatisticsAugmentation); - } - } - - trans.commit(); - } - - @Override - protected InstanceIdentifier listenPath() { - return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Meter.class).build(); - } - - @Override - protected String statName() { - return "Meter Config"; - } - - @Override - public void start(final DataBrokerService dbs) { - if (meterStatsService == null) { - logger.debug("No Meter Statistics service, not subscribing to meter on node {}", getNodeIdentifier()); - return; - } - - super.start(dbs); - } - - @Override - protected MeterConfigStats createInvariantKey(MeterConfigStats item) { - // No invariant data exist in the meter config stats. - return item; - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java deleted file mode 100644 index f43ec693cd..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class MeterStatsTracker extends AbstractListeningStatsTracker { - private static final Logger logger = LoggerFactory.getLogger(MeterStatsTracker.class); - private final OpendaylightMeterStatisticsService meterStatsService; - - MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) { - super(context); - this.meterStatsService = meterStatsService; - } - - @Override - protected void cleanupSingleStat(DataModificationTransaction trans, MeterStats item) { - InstanceIdentifier meterRef = getNodeIdentifierBuilder() - .augmentation(FlowCapableNode.class) - .child(Meter.class,new MeterKey(item.getMeterId())) - .augmentation(NodeMeterStatistics.class).build(); - trans.removeOperationalData(meterRef); - } - - @Override - protected MeterStats updateSingleStat(DataModificationTransaction trans, MeterStats item) { - MeterBuilder meterBuilder = new MeterBuilder(); - MeterKey meterKey = new MeterKey(item.getMeterId()); - meterBuilder.setKey(meterKey); - - InstanceIdentifier meterRef = getNodeIdentifierBuilder() - .augmentation(FlowCapableNode.class).child(Meter.class,meterKey).build(); - - NodeMeterStatisticsBuilder meterStatsBuilder= new NodeMeterStatisticsBuilder(); - meterStatsBuilder.setMeterStatistics(new MeterStatisticsBuilder(item).build()); - - //Update augmented data - meterBuilder.addAugmentation(NodeMeterStatistics.class, meterStatsBuilder.build()); - trans.putOperationalData(meterRef, meterBuilder.build()); - return item; - } - - @Override - public void request() { - if (meterStatsService != null) { - GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(meterStatsService.getAllMeterStatistics(input.build())); - } - } - - @Override - public void onDataChanged(DataChangeEvent, DataObject> change) { - for (InstanceIdentifier key : change.getCreatedConfigurationData().keySet()) { - if (Meter.class.equals(key.getTargetType())) { - request(); - } - } - - final DataModificationTransaction trans = startTransaction(); - for (InstanceIdentifier key : change.getRemovedConfigurationData()) { - if (Meter.class.equals(key.getTargetType())) { - @SuppressWarnings("unchecked") - InstanceIdentifier meter = (InstanceIdentifier)key; - - InstanceIdentifier nodeMeterStatisticsAugmentation = - meter.augmentation(NodeMeterStatistics.class); - trans.removeOperationalData(nodeMeterStatisticsAugmentation); - } - } - trans.commit(); - } - - @Override - protected InstanceIdentifier listenPath() { - return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Meter.class).build(); - } - - @Override - protected String statName() { - return "Meter"; - } - - @Override - public void start(final DataBrokerService dbs) { - if (meterStatsService == null) { - logger.debug("No Meter Statistics service, not subscribing to meters on node {}", getNodeIdentifier()); - return; - } - - super.start(dbs); - } - - @Override - protected MeterStats createInvariantKey(MeterStats item) { - MeterStatsBuilder meterStatsBuilder = new MeterStatsBuilder(); - meterStatsBuilder.setKey(item.getKey()); - meterStatsBuilder.setMeterId(item.getMeterId()); - return meterStatsBuilder.build(); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java deleted file mode 100644 index 425a44946e..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.MultipartTransactionAware; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; - -import com.google.common.base.Preconditions; - -/** - * Main responsibility of the class is to manage multipart response - * for multipart request. It also handles the flow aggregate request - * and response mapping. - * @author avishnoi@in.ibm.com - * - */ -class MultipartMessageManager { - /* - * Map for tx id and type of request, to keep track of all the request sent - * by Statistics Manager. Statistics Manager won't entertain any multipart - * response for which it didn't send the request. - */ - private final Map txIdToRequestTypeMap = new ConcurrentHashMap<>(); - /* - * Map to keep track of the request tx id for flow table statistics request. - * Because flow table statistics multi part response do not contains the table id. - */ - private final Map txIdTotableIdMap = new ConcurrentHashMap<>(); - private final long lifetimeNanos; - - public MultipartMessageManager(long lifetimeNanos) { - this.lifetimeNanos = lifetimeNanos; - } - - private static final class TxIdEntry { - private final TransactionId txId; - - public TxIdEntry(TransactionId txId) { - this.txId = txId; - } - public TransactionId getTxId() { - return txId; - } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((txId == null) ? 0 : txId.hashCode()); - return result; - } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof TxIdEntry)) { - return false; - } - TxIdEntry other = (TxIdEntry) obj; - - if (txId == null) { - if (other.txId != null) { - return false; - } - } else if (!txId.equals(other.txId)) { - return false; - } - return true; - } - - @Override - public String toString() { - return "TxIdEntry [txId=" + txId + ']'; - } - } - - public void recordExpectedTableTransaction(TransactionId id, Short tableId) { - recordExpectedTransaction(id); - txIdTotableIdMap.put(new TxIdEntry(id), Preconditions.checkNotNull(tableId)); - } - - public Short isExpectedTableTransaction(TransactionAware transaction) { - Boolean more = null; - if (transaction instanceof MultipartTransactionAware) { - more = ((MultipartTransactionAware)transaction).isMoreReplies(); - } - - if (!isExpectedTransaction(transaction, more)) { - return null; - } - - final TxIdEntry key = new TxIdEntry(transaction.getTransactionId()); - if (more != null && more.booleanValue()) { - return txIdTotableIdMap.get(key); - } else { - return txIdTotableIdMap.remove(key); - } - } - - public void recordExpectedTransaction(TransactionId id) { - TxIdEntry entry = new TxIdEntry(Preconditions.checkNotNull(id)); - txIdToRequestTypeMap.put(entry, getExpiryTime()); - } - - private boolean isExpectedTransaction(TransactionAware transaction, Boolean more) { - final TxIdEntry entry = new TxIdEntry(transaction.getTransactionId()); - if (more != null && more.booleanValue()) { - return txIdToRequestTypeMap.containsKey(entry); - } else { - return txIdToRequestTypeMap.remove(entry) != null; - } - } - - public boolean isExpectedTransaction(TransactionAware transaction) { - Boolean more = null; - if (transaction instanceof MultipartTransactionAware) { - more = ((MultipartTransactionAware)transaction).isMoreReplies(); - } - - return isExpectedTransaction(transaction, more); - } - - private Long getExpiryTime() { - return System.nanoTime() + lifetimeNanos; - } - - public void cleanStaleTransactionIds() { - final long now = System.nanoTime(); - - for (Iterator it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){ - TxIdEntry txIdEntry = it.next(); - - Long expiryTime = txIdToRequestTypeMap.get(txIdEntry); - if(now > expiryTime){ - it.remove(); - txIdTotableIdMap.remove(txIdEntry); - } - } - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java deleted file mode 100644 index 2e2bf1cd51..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class NodeConnectorStatsTracker extends AbstractStatsTracker { - private static final Logger logger = LoggerFactory.getLogger(NodeConnectorStatsTracker.class); - private final OpendaylightPortStatisticsService portStatsService; - - NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context) { - super(context); - this.portStatsService = portStatsService; - } - - @Override - protected void cleanupSingleStat(final DataModificationTransaction trans, final NodeConnectorStatisticsAndPortNumberMap item) { - // TODO Auto-generated method stub - } - - @Override - protected NodeConnectorStatisticsAndPortNumberMap updateSingleStat(final DataModificationTransaction trans, final NodeConnectorStatisticsAndPortNumberMap item) { - FlowCapableNodeConnectorStatisticsBuilder statisticsBuilder - = new FlowCapableNodeConnectorStatisticsBuilder(); - statisticsBuilder.setBytes(item.getBytes()); - statisticsBuilder.setCollisionCount(item.getCollisionCount()); - statisticsBuilder.setDuration(item.getDuration()); - statisticsBuilder.setPackets(item.getPackets()); - statisticsBuilder.setReceiveCrcError(item.getReceiveCrcError()); - statisticsBuilder.setReceiveDrops(item.getReceiveDrops()); - statisticsBuilder.setReceiveErrors(item.getReceiveErrors()); - statisticsBuilder.setReceiveFrameError(item.getReceiveFrameError()); - statisticsBuilder.setReceiveOverRunError(item.getReceiveOverRunError()); - statisticsBuilder.setTransmitDrops(item.getTransmitDrops()); - statisticsBuilder.setTransmitErrors(item.getTransmitErrors()); - - //Augment data to the node-connector - FlowCapableNodeConnectorStatisticsDataBuilder statisticsDataBuilder = - new FlowCapableNodeConnectorStatisticsDataBuilder(); - - statisticsDataBuilder.setFlowCapableNodeConnectorStatistics(statisticsBuilder.build()); - - final NodeConnectorKey key = new NodeConnectorKey(item.getNodeConnectorId()); - final InstanceIdentifier nodeConnectorRef = getNodeIdentifier().child(NodeConnector.class, key); - - // FIXME: can we bypass this read? - NodeConnector nodeConnector = (NodeConnector)trans.readOperationalData(nodeConnectorRef); - if(nodeConnector != null){ - final FlowCapableNodeConnectorStatisticsData stats = statisticsDataBuilder.build(); - logger.debug("Augmenting port statistics {} to port {}",stats,nodeConnectorRef.toString()); - NodeConnectorBuilder nodeConnectorBuilder = new NodeConnectorBuilder() - .setKey(key).setId(item.getNodeConnectorId()) - .addAugmentation(FlowCapableNodeConnectorStatisticsData.class, stats); - trans.putOperationalData(nodeConnectorRef, nodeConnectorBuilder.build()); - } - - return item; - } - - @Override - public void request() { - if (portStatsService != null) { - final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(portStatsService.getAllNodeConnectorsStatistics(input.build())); - } - } - - @Override - protected NodeConnectorStatisticsAndPortNumberMap createInvariantKey(NodeConnectorStatisticsAndPortNumberMap item) { - NodeConnectorStatisticsAndPortNumberMapBuilder ncStatsBuilder = new NodeConnectorStatisticsAndPortNumberMapBuilder(); - ncStatsBuilder.setNodeConnectorId(item.getNodeConnectorId()); - ncStatsBuilder.setKey(item.getKey()); - return ncStatsBuilder.build(); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java deleted file mode 100644 index db216237d0..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.TimeUnit; - -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.controller.sal.binding.api.data.DataProviderService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsDataBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFeatures; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFeatures; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.AggregateFlowStatistics; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; - -/** - * This class handles the lifecycle of per-node statistics. It receives data - * from StatisticsListener, stores it in the data store and keeps track of - * when the data should be removed. - * - * @author avishnoi@in.ibm.com - */ -public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableContext { - private static final Logger logger = LoggerFactory.getLogger(NodeStatisticsHandler.class); - - private static final long STATS_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(15); - private static final long FIRST_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(5); - private static final int NUMBER_OF_WAIT_CYCLES = 2; - - private final MultipartMessageManager msgManager; - private final StatisticsRequestScheduler srScheduler; - private final InstanceIdentifier targetNodeIdentifier; - private final FlowStatsTracker flowStats; - private final FlowTableStatsTracker flowTableStats; - private final GroupDescStatsTracker groupDescStats; - private final GroupStatsTracker groupStats; - private final MeterConfigStatsTracker meterConfigStats; - private final MeterStatsTracker meterStats; - private final NodeConnectorStatsTracker nodeConnectorStats; - private final QueueStatsTracker queueStats; - private final DataProviderService dps; - private final NodeRef targetNodeRef; - private final NodeKey targetNodeKey; - private final TimerTask task = new TimerTask() { - @Override - public void run() { - try{ - requestPeriodicStatistics(); - cleanStaleStatistics(); - }catch(Exception e){ - logger.warn("Exception occured while sending statistics request : {}",e); - } - } - }; - - public NodeStatisticsHandler(final DataProviderService dps, final NodeKey nodeKey, - final OpendaylightFlowStatisticsService flowStatsService, - final OpendaylightFlowTableStatisticsService flowTableStatsService, - final OpendaylightGroupStatisticsService groupStatsService, - final OpendaylightMeterStatisticsService meterStatsService, - final OpendaylightPortStatisticsService portStatsService, - final OpendaylightQueueStatisticsService queueStatsService, - final StatisticsRequestScheduler srScheduler) { - this.dps = Preconditions.checkNotNull(dps); - this.targetNodeKey = Preconditions.checkNotNull(nodeKey); - this.srScheduler = Preconditions.checkNotNull(srScheduler); - this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build(); - this.targetNodeRef = new NodeRef(targetNodeIdentifier); - - final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES); - - msgManager = new MultipartMessageManager(lifetimeNanos); - flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this); - flowStats = new FlowStatsTracker(flowStatsService, this, flowTableStats); - groupDescStats = new GroupDescStatsTracker(groupStatsService, this); - groupStats = new GroupStatsTracker(groupStatsService, this); - meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this); - meterStats = new MeterStatsTracker(meterStatsService, this); - nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this); - queueStats = new QueueStatsTracker(queueStatsService, this); - } - - public NodeKey getTargetNodeKey() { - return targetNodeKey; - } - - @Override - public InstanceIdentifier getNodeIdentifier() { - return targetNodeIdentifier; - } - - @Override - public NodeRef getNodeRef() { - return targetNodeRef; - } - - @Override - public DataModificationTransaction startDataModification() { - DataModificationTransaction dmt = dps.beginTransaction(); - dmt.registerListener(this.srScheduler); - return dmt; - } - - public synchronized void updateGroupDescStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - groupDescStats.updateStats(list); - } - } - - public synchronized void updateGroupStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - groupStats.updateStats(list); - } - } - - public synchronized void updateMeterConfigStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - meterConfigStats.updateStats(list); - } - } - - public synchronized void updateMeterStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - meterStats.updateStats(list); - } - } - - public synchronized void updateQueueStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - queueStats.updateStats(list); - } - } - - public synchronized void updateFlowTableStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - flowTableStats.updateStats(list); - } - } - - public synchronized void updateNodeConnectorStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - nodeConnectorStats.updateStats(list); - } - } - - public synchronized void updateAggregateFlowStats(TransactionAware transaction, AggregateFlowStatistics flowStats) { - final Short tableId = msgManager.isExpectedTableTransaction(transaction); - if (tableId != null) { - final DataModificationTransaction trans = this.startDataModification(); - InstanceIdentifier
tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey) - .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance(); - - AggregateFlowStatisticsDataBuilder aggregateFlowStatisticsDataBuilder = new AggregateFlowStatisticsDataBuilder(); - AggregateFlowStatisticsBuilder aggregateFlowStatisticsBuilder = new AggregateFlowStatisticsBuilder(flowStats); - - aggregateFlowStatisticsDataBuilder.setAggregateFlowStatistics(aggregateFlowStatisticsBuilder.build()); - - logger.debug("Augment aggregate statistics: {} for table {} on Node {}", - aggregateFlowStatisticsBuilder.build().toString(),tableId,targetNodeKey); - - TableBuilder tableBuilder = new TableBuilder(); - tableBuilder.setKey(new TableKey(tableId)); - tableBuilder.addAugmentation(AggregateFlowStatisticsData.class, aggregateFlowStatisticsDataBuilder.build()); - trans.putOperationalData(tableRef, tableBuilder.build()); - - trans.commit(); - } - } - - public synchronized void updateFlowStats(TransactionAware transaction, List list) { - if (msgManager.isExpectedTransaction(transaction)) { - flowStats.updateStats(list); - } - } - - public synchronized void updateGroupFeatures(GroupFeatures notification) { - final DataModificationTransaction trans = this.startDataModification(); - - final NodeBuilder nodeData = new NodeBuilder(); - nodeData.setKey(targetNodeKey); - - NodeGroupFeaturesBuilder nodeGroupFeatures = new NodeGroupFeaturesBuilder(); - GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder(notification); - nodeGroupFeatures.setGroupFeatures(groupFeatures.build()); - - //Update augmented data - nodeData.addAugmentation(NodeGroupFeatures.class, nodeGroupFeatures.build()); - trans.putOperationalData(targetNodeIdentifier, nodeData.build()); - - // FIXME: should we be tracking this data? - trans.commit(); - } - - public synchronized void updateMeterFeatures(MeterFeatures features) { - final DataModificationTransaction trans = this.startDataModification(); - - final NodeBuilder nodeData = new NodeBuilder(); - nodeData.setKey(targetNodeKey); - - NodeMeterFeaturesBuilder nodeMeterFeatures = new NodeMeterFeaturesBuilder(); - MeterFeaturesBuilder meterFeature = new MeterFeaturesBuilder(features); - nodeMeterFeatures.setMeterFeatures(meterFeature.build()); - - //Update augmented data - nodeData.addAugmentation(NodeMeterFeatures.class, nodeMeterFeatures.build()); - trans.putOperationalData(targetNodeIdentifier, nodeData.build()); - - // FIXME: should we be tracking this data? - trans.commit(); - } - - public synchronized void cleanStaleStatistics() { - final DataModificationTransaction trans = this.startDataModification(); - - flowStats.cleanup(trans); - groupDescStats.cleanup(trans); - groupStats.cleanup(trans); - meterConfigStats.cleanup(trans); - meterStats.cleanup(trans); - nodeConnectorStats.cleanup(trans); - queueStats.cleanup(trans); - msgManager.cleanStaleTransactionIds(); - - trans.commit(); - } - - public synchronized void requestPeriodicStatistics() { - logger.debug("Send requests for statistics collection to node : {}", targetNodeKey); - - this.srScheduler.addRequestToSchedulerQueue(flowTableStats); - - this.srScheduler.addRequestToSchedulerQueue(flowStats); - - this.srScheduler.addRequestToSchedulerQueue(nodeConnectorStats); - - this.srScheduler.addRequestToSchedulerQueue(groupStats); - - this.srScheduler.addRequestToSchedulerQueue(groupDescStats); - - this.srScheduler.addRequestToSchedulerQueue(meterStats); - - this.srScheduler.addRequestToSchedulerQueue(meterConfigStats); - - this.srScheduler.addRequestToSchedulerQueue(queueStats); - } - - public synchronized void start(final Timer timer) { - flowStats.start(dps); - groupDescStats.start(dps); - groupStats.start(dps); - meterConfigStats.start(dps); - meterStats.start(dps); - queueStats.start(dps); - - timer.schedule(task, (long) (Math.random() * FIRST_COLLECTION_MILLIS), STATS_COLLECTION_MILLIS); - - logger.debug("Statistics handler for node started with base interval {}ms", STATS_COLLECTION_MILLIS); - - requestPeriodicStatistics(); - } - - @Override - public synchronized void close() { - task.cancel(); - flowStats.close(); - groupDescStats.close(); - groupStats.close(); - meterConfigStats.close(); - meterStats.close(); - queueStats.close(); - - //Clean up queued statistics request from scheduler queue - srScheduler.removeRequestsFromSchedulerQueue(this.getNodeRef()); - - logger.debug("Statistics handler for {} shut down", targetNodeKey.getId()); - } - - @Override - public void registerTransaction(TransactionId id) { - msgManager.recordExpectedTransaction(id); - logger.debug("Transaction {} for node {} sent successfully", id, targetNodeKey); - } - - @Override - public void registerTableTransaction(final TransactionId id, final Short table) { - msgManager.recordExpectedTableTransaction(id, table); - logger.debug("Transaction {} for node {} table {} sent successfully", id, targetNodeKey, table); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsEntry.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsEntry.java deleted file mode 100644 index d1f2529de8..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsEntry.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; - -final class QueueStatsEntry { - private final NodeConnectorId nodeConnectorId; - private final QueueId queueId; - public QueueStatsEntry(NodeConnectorId ncId, QueueId queueId){ - this.nodeConnectorId = ncId; - this.queueId = queueId; - } - public NodeConnectorId getNodeConnectorId() { - return nodeConnectorId; - } - public QueueId getQueueId() { - return queueId; - } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((nodeConnectorId == null) ? 0 : nodeConnectorId.hashCode()); - result = prime * result + ((queueId == null) ? 0 : queueId.hashCode()); - return result; - } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof QueueStatsEntry)) { - return false; - } - QueueStatsEntry other = (QueueStatsEntry) obj; - if (nodeConnectorId == null) { - if (other.nodeConnectorId != null) { - return false; - } - } else if (!nodeConnectorId.equals(other.nodeConnectorId)) { - return false; - } - if (queueId == null) { - if (other.queueId != null) { - return false; - } - } else if (!queueId.equals(other.queueId)) { - return false; - } - return true; - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java deleted file mode 100644 index 4a589703be..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.Map.Entry; - -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsDataBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPortInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class QueueStatsTracker extends AbstractListeningStatsTracker { - private static final Logger logger = LoggerFactory.getLogger(QueueStatsTracker.class); - private final OpendaylightQueueStatisticsService queueStatsService; - - QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context) { - super(context); - this.queueStatsService = queueStatsService; - } - - @Override - protected void cleanupSingleStat(DataModificationTransaction trans, QueueStatsEntry item) { - InstanceIdentifier queueRef - = getNodeIdentifierBuilder().child(NodeConnector.class, new NodeConnectorKey(item.getNodeConnectorId())) - .augmentation(FlowCapableNodeConnector.class) - .child(Queue.class, new QueueKey(item.getQueueId())) - .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).build(); - trans.removeOperationalData(queueRef); - } - - @Override - protected QueueStatsEntry updateSingleStat(DataModificationTransaction trans, QueueIdAndStatisticsMap item) { - - QueueStatsEntry queueEntry = new QueueStatsEntry(item.getNodeConnectorId(), item.getQueueId()); - - FlowCapableNodeConnectorQueueStatisticsDataBuilder queueStatisticsDataBuilder = new FlowCapableNodeConnectorQueueStatisticsDataBuilder(); - - FlowCapableNodeConnectorQueueStatisticsBuilder queueStatisticsBuilder = new FlowCapableNodeConnectorQueueStatisticsBuilder(); - - queueStatisticsBuilder.fieldsFrom(item); - - queueStatisticsDataBuilder.setFlowCapableNodeConnectorQueueStatistics(queueStatisticsBuilder.build()); - - InstanceIdentifier queueRef = getNodeIdentifierBuilder().child(NodeConnector.class, new NodeConnectorKey(item.getNodeConnectorId())) - .augmentation(FlowCapableNodeConnector.class) - .child(Queue.class, new QueueKey(item.getQueueId())).toInstance(); - - QueueBuilder queueBuilder = new QueueBuilder(); - FlowCapableNodeConnectorQueueStatisticsData qsd = queueStatisticsDataBuilder.build(); - queueBuilder.addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, qsd); - queueBuilder.setKey(new QueueKey(item.getQueueId())); - - logger.debug("Augmenting queue statistics {} of queue {} to port {}", - qsd, - item.getQueueId(), - item.getNodeConnectorId()); - - trans.putOperationalData(queueRef, queueBuilder.build()); - return queueEntry; - } - - @Override - public void request() { - if (queueStatsService != null) { - GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder(); - input.setNode(getNodeRef()); - - requestHelper(queueStatsService.getAllQueuesStatisticsFromAllPorts(input.build())); - } - } - - public void request(NodeConnectorId nodeConnectorId, QueueId queueId) { - if (queueStatsService != null) { - GetQueueStatisticsFromGivenPortInputBuilder input = new GetQueueStatisticsFromGivenPortInputBuilder(); - - input.setNode(getNodeRef()); - input.setNodeConnectorId(nodeConnectorId); - input.setQueueId(queueId); - - requestHelper(queueStatsService.getQueueStatisticsFromGivenPort(input.build())); - } - } - - @Override - public void onDataChanged(DataChangeEvent, DataObject> change) { - for (Entry, DataObject> e : change.getCreatedConfigurationData().entrySet()) { - if (Queue.class.equals(e.getKey().getTargetType())) { - final Queue queue = (Queue) e.getValue(); - final NodeConnectorKey key = e.getKey().firstKeyOf(NodeConnector.class, NodeConnectorKey.class); - logger.debug("Key {} triggered request for connector {} queue {}", key.getId(), queue.getQueueId()); - request(key.getId(), queue.getQueueId()); - } else { - logger.debug("Ignoring key {}", e.getKey()); - } - } - - final DataModificationTransaction trans = startTransaction(); - for (InstanceIdentifier key : change.getRemovedConfigurationData()) { - if (Queue.class.equals(key.getTargetType())) { - @SuppressWarnings("unchecked") - final InstanceIdentifier queue = (InstanceIdentifier)key; - final InstanceIdentifier del = queue - .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class); - logger.debug("Key {} triggered remove of augmentation {}", key, del); - - trans.removeOperationalData(del); - } - } - trans.commit(); - } - - @Override - protected InstanceIdentifier listenPath() { - return getNodeIdentifierBuilder().child(NodeConnector.class) - .augmentation(FlowCapableNodeConnector.class).child(Queue.class).build(); - } - - @Override - protected String statName() { - return "Queue"; - } - - @Override - public void start(final DataBrokerService dbs) { - if (queueStatsService == null) { - logger.debug("No Queue Statistics service, not subscribing to queues on node {}", getNodeIdentifier()); - return; - } - - super.start(dbs); - } - - @Override - protected QueueStatsEntry createInvariantKey(QueueStatsEntry item) { - // No invariant data exist in the group description stats. - return item; - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatListeningCommiter.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatListeningCommiter.java new file mode 100644 index 0000000000..7589c72a45 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatListeningCommiter.java @@ -0,0 +1,34 @@ +/** + * 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.md.statistics.manager; + +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.NotificationListener; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager + * + * StatListeningCommiter + * Definition Interface for {@link DataChangeListener} implementer class rule. + * Interface represent a contract between Config/DataStore changes and + * Operational/DataStore commits. All Operational/DataStore commit have + * to by represent as RPC Device response Notification processing. So + * Operational/DS could contains only real mirror of OF Device + * + * @author Vaclav Demcak + * + * Created: Aug 27, 2014 + */ +public interface StatListeningCommiter extends DataChangeListener, StatNotifyCommiter { + + +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNodeRegistration.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNodeRegistration.java new file mode 100644 index 0000000000..80a15a3230 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNodeRegistration.java @@ -0,0 +1,50 @@ +/** + * 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.md.statistics.manager; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatNodeRegistration + * Class represents {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode} + * {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener} in Operational/DataStore for ADD / REMOVE + * actions which are represented connect / disconnect OF actions. Connect functionality are expecting + * + * @author Vaclav Demcak + * + * Created: Sep 5, 2014 + */ +public interface StatNodeRegistration extends OpendaylightInventoryListener, AutoCloseable { + + /** + * Method contains {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode} registration to {@link StatisticsManager} + * for permanently collecting statistics by {@link StatPermCollector} and + * as a prevention to use a validation check to the Operational/DS for identify + * connected {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode}. + * + * @param InstanceIdentifier keyIdent + * @param FlowCapableNode data + * @param InstanceIdentifier nodeIdent + */ + void connectFlowCapableNode(InstanceIdentifier keyIdent, + SwitchFeatures data, InstanceIdentifier nodeIdent); + + /** + * Method cut {@link Node} registration for {@link StatPermCollector} + * + * @param InstanceIdentifier keyIdent + */ + void disconnectFlowCapableNode(InstanceIdentifier keyIdent); +} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNotifyCommiter.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNotifyCommiter.java new file mode 100644 index 0000000000..0392e47817 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatNotifyCommiter.java @@ -0,0 +1,31 @@ +/** + * 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.md.statistics.manager; + +import org.opendaylight.yangtools.yang.binding.NotificationListener; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager + * + * StatNotifyCommiter + * Definition Interface for notification implementer class rule + * Interface represent a contract between RPC Device Notification + * and Operational/DataStore commits. + * + * + * @author Vaclav Demcak + * + * Created: Aug 28, 2014 + */ +public interface StatNotifyCommiter extends AutoCloseable, NotificationListener { + + +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatPermCollector.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatPermCollector.java new file mode 100644 index 0000000000..9116e66737 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatPermCollector.java @@ -0,0 +1,115 @@ +/** + * 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.md.statistics.manager; + +import java.util.List; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager + * + * StatPermCollector + * Class implement {@link Runnable} and inside is running statistic collecting + * process DataObject statistics by DataObject statistics for every {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode}. + * Every statistics wait to finish previous statistics. Only if all statistics finish, + * next {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode} + * Statistics should be collecting. We are able to set minimal time for start next round cross all Network, + * but all depends on network possibility. + * + * @author Vaclav Demcak + * + * Created: Aug 28, 2014 + */ +public interface StatPermCollector extends Runnable, AutoCloseable { + + /** + * StatCapType + * Enum class refers ofp_statistics capabilities fields from OF Switch + * capabilities specification which have to come as a post HandShake + * information from OF Switch and Inventory Manager adds all to the + * Operational/DS. + * If the capabilities are not add (for any reason) NodeRegistrator + * adds all StatCapTypes for the {@link Node}. + */ + public enum StatCapabTypes { + /** + * OFPC_FLOW_STATS + */ + FLOW_STATS, + /** + * OFPC_TABLE_STATS + */ + TABLE_STATS, + /** + * OFPC_PORT_STATS + */ + PORT_STATS, + /** + * OFPC_GROUP_STATS + */ + GROUP_STATS, + /** + * OFPC_QUEUE_STATS + */ + QUEUE_STATS, + /** + * Meter statistics has no support from OF Switch capabilities + * so we have to try get statistics for it and wait for response + * Error or response package with results. + */ + METER_STATS + } + + /** + * Add new connected node for permanent statistics collecting process + * + * @param flowNode + * @param statTypes + * @param nrOfSwitchTables + * @return true/false if the {@link Node} added successful + */ + boolean connectedNodeRegistration(InstanceIdentifier nodeIdent, + List statTypes, Short nrOfSwitchTables); + + /** + * All disconnected Nodes need be removed from stat list Nodes + * @param flowNode + * @return true/false if the {@link Node} removed successful + */ + boolean disconnectedNodeUnregistration(InstanceIdentifier nodeIdent); + + /** + * Method return true only and only if {@link StatPermCollector} contain + * valid node registration in its internal {@link Node} map. + * Otherwise return false. + * + * @param InstanceIdentifier flowNode + * @return + */ + boolean isProvidedFlowNodeActive(InstanceIdentifier nodeIdent); + + /** + * Object notification for continue statistics collecting process. + * It is call from collecting allStatistics methods as a future result for + * Operational/DS statistic store call (does not matter in the outcome). + */ + void collectNextStatistics(); + + /** + * Method returns true if collector has registered some active nodes + * otherwise return false. + * + * @return + */ + boolean hasActiveNodes(); +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatRpcMsgManager.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatRpcMsgManager.java new file mode 100644 index 0000000000..0576c2a645 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatRpcMsgManager.java @@ -0,0 +1,191 @@ +/** + * 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.md.statistics.manager; + +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.common.RpcResult; + +import com.google.common.base.Optional; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager + * + * StatRpcMsgManager + * It represent access point for Device statistics RPC services which are + * filtered for needed methods only and they are wrapped in simply way. + * Many statistics responses are Multipart messages, so StatRpcMsgManager + * provide a functionality to add all multipart msg and provides back whole + * stack to listener when listener catch the last Multipart msg. + * + * @author Vaclav Demcak + * + * Created: Aug 29, 2014 + */ +public interface StatRpcMsgManager extends Runnable, AutoCloseable { + + interface RpcJobsQueue extends Callable {} + + /** + * Transaction container is definition for Multipart transaction + * join container for all Multipart msg with same TransactionId + * Input {@link DataObject} is a possible light-weight DataObject + * which is used for identification (e.g. Flow-> Priority,Match,Cookie,FlowId) + * + * @param extends TransactionAware - + */ + interface TransactionCacheContainer { + + void addNotif(T notification); + + TransactionId getId(); + + NodeId getNodeId(); + + Optional getConfInput(); + + List getNotifications(); + } + + /** + * Method is used for check a transaction registration + * for multipart cache holder + * + * @param TransactionId id + * @return true if the transaction has been correctly registered + */ + Future isExpectedStatistics(TransactionId id, NodeId nodeId); + + /** + * Method converts {@link java.util.concurrent.Future} object to listenenable future which + * is registered for Multipart Notification Statistics Collecting processing. + * + * @param future - result every Device RPC call + */ + void registrationRpcFutureCallBack(Future> future, D inputObj, NodeRef ref); + + /** + * Method adds Notification which is marked as Multipart to the transaction cash + * to wait for the last one. + * + * @param notification + */ + void addNotification(T notification, NodeId nodeId); + + /** + * The last Multipart should inform code about possibility to take all previous + * messages for next processing. The method take all msg and possible input object + * and build all to TransactionCacheContainer Object to return. This process clean + * all instances in Cache. + * + * @param TransactionId id + * @return TransactionCacheContainer + */ + Future>> getTransactionCacheContainer(TransactionId id, NodeId nodeId); + + /** + * Method wraps OpendaylightGroupStatisticsService.getAllGroupStatistics + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllGroupsStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightGroupStatisticsService.getGroupDescription + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllGroupsConfStats(NodeRef nodeRef); + + /** + * Method wraps OpendaylightMeterStatisticsService.getGroupFeatures + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getGroupFeaturesStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightMeterStatisticsService.getAllMeterStatistics + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllMetersStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightMeterStatisticsService.getAllMeterConfigStatistics + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllMeterConfigStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightMeterStatisticsService.getMeterFeatures + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getMeterFeaturesStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightFlowStatisticsService.getAllFlowsStatisticsFromAllFlowTables + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllFlowsStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightFlowStatisticsService.getAggregateFlowStatisticsFromFlowTableForAllFlows + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + * @param TableId tableId + */ + void getAggregateFlowStat(NodeRef nodeRef, TableId tableId); + + /** + * Method wraps OpendaylightPortStatisticsService.getAllNodeConnectorsStatistics + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllPortsStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightFlowTableStatisticsService.getFlowTablesStatistics + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllTablesStat(NodeRef nodeRef); + + /** + * Method wraps OpendaylightQueueStatisticsService.getAllQueuesStatisticsFromAllPorts + * and registers to Transaction Cache + * + * @param NodeRef nodeRef + */ + void getAllQueueStat(NodeRef nodeRef); + +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsListener.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsListener.java deleted file mode 100644 index a06f7efdbb..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsListener.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdated; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdated; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class is responsible for listening for statistics update notifications and - * routing them to the appropriate NodeStatisticsHandler. - - * TODO: Need to add error message listener and clean-up the associated tx id - * if it exists in the tx-id cache. - * @author vishnoianil - */ -public class StatisticsListener implements OpendaylightGroupStatisticsListener, - OpendaylightMeterStatisticsListener, - OpendaylightFlowStatisticsListener, - OpendaylightPortStatisticsListener, - OpendaylightFlowTableStatisticsListener, - OpendaylightQueueStatisticsListener{ - - private final static Logger sucLogger = LoggerFactory.getLogger(StatisticsListener.class); - private final StatisticsProvider statisticsManager; - - /** - * default ctor - * @param manager - */ - public StatisticsListener(final StatisticsProvider manager){ - this.statisticsManager = manager; - } - - @Override - public void onMeterConfigStatsUpdated(final MeterConfigStatsUpdated notification) { - final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateMeterConfigStats(notification, notification.getMeterConfigStats()); - } - } - - @Override - public void onMeterStatisticsUpdated(MeterStatisticsUpdated notification) { - final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateMeterStats(notification, notification.getMeterStats()); - } - } - - @Override - public void onGroupDescStatsUpdated(GroupDescStatsUpdated notification) { - final NodeStatisticsHandler handler = statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateGroupDescStats(notification, notification.getGroupDescStats()); - } - } - - @Override - public void onGroupStatisticsUpdated(GroupStatisticsUpdated notification) { - final NodeStatisticsHandler handler = statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateGroupStats(notification, notification.getGroupStats()); - } - } - - @Override - public void onMeterFeaturesUpdated(MeterFeaturesUpdated notification) { - final NodeStatisticsHandler sna = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (sna != null) { - sna.updateMeterFeatures(notification); - } - } - - @Override - public void onGroupFeaturesUpdated(GroupFeaturesUpdated notification) { - final NodeStatisticsHandler sna = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (sna != null) { - sna.updateGroupFeatures(notification); - } - } - - @Override - public void onFlowsStatisticsUpdate(final FlowsStatisticsUpdate notification) { - sucLogger.debug("Received flow stats update : {}",notification.toString()); - final NodeStatisticsHandler sna = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (sna != null) { - sna.updateFlowStats(notification, notification.getFlowAndStatisticsMapList()); - } - } - - @Override - public void onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) { - final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateAggregateFlowStats(notification, notification); - } - } - - @Override - public void onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) { - final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateNodeConnectorStats(notification, notification.getNodeConnectorStatisticsAndPortNumberMap()); - } - } - - @Override - public void onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) { - final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateFlowTableStats(notification, notification.getFlowTableAndStatisticsMap()); - } - } - - @Override - public void onQueueStatisticsUpdate(QueueStatisticsUpdate notification) { - final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId()); - if (handler != null) { - handler.updateQueueStats(notification, notification.getQueueIdAndStatisticsMap()); - } - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java new file mode 100644 index 0000000000..b53c54e360 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java @@ -0,0 +1,179 @@ +/** + * 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.md.statistics.manager; + +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; +import org.opendaylight.controller.md.statistics.manager.StatPermCollector.StatCapabTypes; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsListener; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager + * + * StatisticsManager + * It represent a central point for whole module. Implementation + * StatisticsManager registers all Operation/DS {@link StatNotifyCommiter} and + * Config/DS {@StatListeningCommiter}, as well as {@link StatPermCollector} + * for statistic collecting and {@link StatRpcMsgManager} as Device RPCs provider. + * In next, StatisticsManager provides all DS contact Transaction services. + * + * @author Vaclav Demcak + * + * Created: Aug 27, 2014 + */ +public interface StatisticsManager extends AutoCloseable, TransactionChainListener { + + /** + * StatDataStoreOperation + * Interface represent functionality to submit changes to DataStore. + * Internal {@link TransactionChainListener} joining all DS commits + * to Set of chained changes for prevent often DataStore touches. + */ + public interface StatDataStoreOperation { + + /** + * Apply all read / write (put|merge) operation + * for DataStore + * @param {@link ReadWriteTransaction} tx + */ + void applyOperation(ReadWriteTransaction tx); + + } + + /** + * Method starts whole StatisticManager functionality + * + * @param {@link NotificationProviderService} notifService + * @param {@link RpcConsumerRegistry} rpcRegistry + * @param minReqNetMonitInt + */ + void start(final NotificationProviderService notifService, + final RpcConsumerRegistry rpcRegistry, final long minReqNetMonitInt); + + /** + * Method provides read/write DataStore functionality cross applyOperation + * defined in {@link StatDataStoreOperation} + * + * @param inventoryOper - operation for DataStore + */ + void enqueue(final StatDataStoreOperation inventoryOper); + + /** + * Method wraps {@link StatisticCollector}.isProvidedFlowNodeActive method + * to provide parallel statCollection process for Set of Nodes. So it has to + * identify correct Node Set by NodeIdentifier + * + * @param nodeIdent + */ + boolean isProvidedFlowNodeActive(InstanceIdentifier nodeIdent); + + /** + * Method wraps {@link StatPermCollector}.collectNextStatistics to provide + * parallel statCollection process for Set of Nodes. So it has to + * identify correct Node Set by NodeIdentifier. + * + * @param nodeIdent + */ + void collectNextStatistics(InstanceIdentifier nodeIdent); + + /** + * Method wraps {@link StatPermCollector}.connectedNodeRegistration to provide + * parallel statCollection process for Set of Nodes. So it has to + * connect node to new or not full Node statCollector Set. + * + * @param nodeIdent + * @param statTypes + * @param nrOfSwitchTables + */ + void connectedNodeRegistration(InstanceIdentifier nodeIdent, + List statTypes, Short nrOfSwitchTables); + + /** + * Method wraps {@link StatPermCollector}.disconnectedNodeUnregistration to provide + * parallel statCollection process for Set of Nodes. So it has to identify + * correct collector for disconnect node. + * + * @param nodeIdent + */ + void disconnectedNodeUnregistration(InstanceIdentifier nodeIdent); + + /** + * Method provides access to Device RPC methods by wrapped + * internal method. In next {@link StatRpcMsgManager} is registered all + * Multipart device msg response and joining all to be able run all + * collected statistics in one time (easy identification Data for delete) + * + * @return {@link StatRpcMsgManager} + */ + StatRpcMsgManager getRpcMsgManager(); + + /** + * Define Method : {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode} + * Operational/DS data change listener -> impl. target -> register FlowCapableNode to Statistic Collecting process + * @return {@link StatNodeRegistration} + */ + StatNodeRegistration getNodeRegistrator(); + + /** + * Define Method : Flow Config/DS data change listener -> impl. target -> + * -> make pair between Config/DS FlowId and Device Flow response Hash + * @return + */ + StatListeningCommiter getFlowListenComit(); + + /** + * Define Method : Meter Config/DS data change listener and Operation/DS notify commit + * functionality + * @return + */ + StatListeningCommiter getMeterListenCommit(); + + /** + * Define Method : Group Config/DS data change listener and Operation/DS notify commit + * functionality + * @return + */ + StatListeningCommiter getGroupListenCommit(); + + /** + * Define Method : Queue Config/DS change listener and Operation/DS notify commit functionality + * @return + */ + StatListeningCommiter getQueueNotifyCommit(); + + /** + * Define Method : Table Operation/DS notify commit functionality + * @return + */ + StatNotifyCommiter getTableNotifCommit(); + + /** + * Define Method : Port Operation/DS notify commit functionality + * @return + */ + StatNotifyCommiter getPortNotifyCommit(); + +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java index 5bcbef119a..912a6eda4b 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java @@ -8,29 +8,66 @@ package org.opendaylight.controller.md.statistics.manager; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.statistics.manager.impl.StatisticsManagerImpl; import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; -import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.common.annotations.VisibleForTesting; + +/** + * Statistics Manager Activator + * + * OSGi bundle activator + * + */ public class StatisticsManagerActivator extends AbstractBindingAwareProvider { - private StatisticsProvider statsProvider; + + private final static Logger LOG = LoggerFactory.getLogger(StatisticsManagerActivator.class); + + /* TODO move it to ConfigSubsystem */ + private static final long DEFAULT_MIN_REQUEST_NET_MONITOR_INTERVAL = 3000L; + private static final int MAX_NODES_FOR_COLLECTOR = 8; + + private StatisticsManager statsProvider; @Override - public void onSessionInitiated(ProviderContext session) { - final DataProviderService dps = session.getSALService(DataProviderService.class); - final NotificationProviderService nps = session.getSALService(NotificationProviderService.class); + public void onSessionInitiated(final ProviderContext session) { + LOG.info("StatisticsManagerActivator initialization."); + try { + final DataBroker dataBroker = session.getSALService(DataBroker.class); + final NotificationProviderService notifService = + session.getSALService(NotificationProviderService.class); + statsProvider = new StatisticsManagerImpl(dataBroker, MAX_NODES_FOR_COLLECTOR); + statsProvider.start(notifService, session, DEFAULT_MIN_REQUEST_NET_MONITOR_INTERVAL); + LOG.info("StatisticsManagerActivator started successfully."); + } + catch (final Exception e) { + LOG.error("Unexpected error by initialization of StatisticsManagerActivator", e); + stopImpl(null); + } + } - statsProvider = new StatisticsProvider(dps); - statsProvider.start(nps, session); + @VisibleForTesting + StatisticsManager getStatisticManager() { + return statsProvider; } @Override - protected void stopImpl(BundleContext context) { + protected void stopImpl(final BundleContext context) { if (statsProvider != null) { - statsProvider.close(); + try { + statsProvider.close(); + } + catch (final Exception e) { + LOG.error("Unexpected error by stopping StatisticsManagerActivator", e); + } statsProvider = null; } + LOG.info("StatisticsManagerActivator stoped."); } } diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java deleted file mode 100644 index 8c9b60e43f..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.Collection; -import java.util.Timer; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.opendaylight.controller.sal.binding.api.NotificationProviderService; -import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry; -import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; -import org.opendaylight.controller.sal.binding.api.data.DataProviderService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.NotificationListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; - -/** - * Following are main responsibilities of the class: - * 1) Invoke statistics request thread to send periodic statistics request to all the - * flow capable switch connected to the controller. It sends statistics request for - * Group,Meter,Table,Flow,Queue,Aggregate stats. - * - * 2) Invoke statistics ager thread, to clean up all the stale statistics data from - * operational data store. - * - * @author avishnoi@in.ibm.com - * - */ -public class StatisticsProvider implements AutoCloseable { - private static final Logger spLogger = LoggerFactory.getLogger(StatisticsProvider.class); - - private final ConcurrentMap handlers = new ConcurrentHashMap<>(); - private final Timer timer = new Timer("statistics-manager", true); - private final DataProviderService dps; - - private OpendaylightGroupStatisticsService groupStatsService; - - private OpendaylightMeterStatisticsService meterStatsService; - - private OpendaylightFlowStatisticsService flowStatsService; - - private OpendaylightPortStatisticsService portStatsService; - - private OpendaylightFlowTableStatisticsService flowTableStatsService; - - private OpendaylightQueueStatisticsService queueStatsService; - - private final StatisticsRequestScheduler srScheduler; - - public StatisticsProvider(final DataProviderService dataService) { - this.dps = Preconditions.checkNotNull(dataService); - this.srScheduler = new StatisticsRequestScheduler(); - } - - private final StatisticsListener updateCommiter = new StatisticsListener(StatisticsProvider.this); - - private ListenerRegistration listenerRegistration; - - private ListenerRegistration flowCapableTrackerRegistration; - - public void start(final NotificationProviderService nps, final RpcConsumerRegistry rpcRegistry) { - - // Get Group/Meter statistics service instances - groupStatsService = rpcRegistry.getRpcService(OpendaylightGroupStatisticsService.class); - meterStatsService = rpcRegistry.getRpcService(OpendaylightMeterStatisticsService.class); - flowStatsService = rpcRegistry.getRpcService(OpendaylightFlowStatisticsService.class); - portStatsService = rpcRegistry.getRpcService(OpendaylightPortStatisticsService.class); - flowTableStatsService = rpcRegistry.getRpcService(OpendaylightFlowTableStatisticsService.class); - queueStatsService = rpcRegistry.getRpcService(OpendaylightQueueStatisticsService.class); - this.srScheduler.start(); - - // Start receiving notifications - this.listenerRegistration = nps.registerNotificationListener(this.updateCommiter); - - // Register for switch connect/disconnect notifications - final InstanceIdentifier fcnId = InstanceIdentifier.builder(Nodes.class) - .child(Node.class).augmentation(FlowCapableNode.class).build(); - spLogger.debug("Registering FlowCapable tracker to {}", fcnId); - this.flowCapableTrackerRegistration = dps.registerDataChangeListener(fcnId, - new FlowCapableTracker(this, fcnId)); - - spLogger.info("Statistics Provider started."); - } - - /** - * Get the handler for a particular node. - * - * @param nodeId source node - * @return Node statistics handler for that node. Null if the statistics should - * not handled. - */ - public final NodeStatisticsHandler getStatisticsHandler(final NodeId nodeId) { - Preconditions.checkNotNull(nodeId); - NodeStatisticsHandler handler = handlers.get(nodeId); - if (handler == null) { - spLogger.info("Attempted to get non-existing handler for {}", nodeId); - } - return handler; - } - - @Override - public void close() { - try { - if (this.listenerRegistration != null) { - this.listenerRegistration.close(); - this.listenerRegistration = null; - } - if (this.flowCapableTrackerRegistration != null) { - this.flowCapableTrackerRegistration.close(); - this.flowCapableTrackerRegistration = null; - } - timer.cancel(); - } catch (Exception e) { - spLogger.warn("Failed to stop Statistics Provider completely", e); - } finally { - spLogger.info("Statistics Provider stopped."); - } - } - - void startNodeHandlers(final Collection addedNodes) { - for (NodeKey key : addedNodes) { - if (handlers.containsKey(key.getId())) { - spLogger.warn("Attempted to start already-existing handler for {}, very strange", key.getId()); - continue; - } - - final NodeStatisticsHandler h = new NodeStatisticsHandler(dps, key, - flowStatsService, flowTableStatsService, groupStatsService, - meterStatsService, portStatsService, queueStatsService,srScheduler); - final NodeStatisticsHandler old = handlers.putIfAbsent(key.getId(), h); - if (old == null) { - spLogger.debug("Started node handler for {}", key.getId()); - h.start(timer); - } else { - spLogger.debug("Prevented race on handler for {}", key.getId()); - } - } - } - - void stopNodeHandlers(final Collection removedNodes) { - for (NodeKey key : removedNodes) { - final NodeStatisticsHandler s = handlers.remove(key.getId()); - if (s != null) { - spLogger.debug("Stopping node handler for {}", key.getId()); - s.close(); - } else { - spLogger.warn("Attempted to remove non-existing handler for {}, very strange", key.getId()); - } - } - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java deleted file mode 100644 index 29a27e2bb2..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright IBM Corporation, 2013. 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.md.statistics.manager; - -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.TimeUnit; - -import org.opendaylight.controller.md.sal.common.api.TransactionStatus; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Main responsibility of the class is to check the MD-SAL data store read/write - * transaction accumulation level and send statistics request if number of pending - * read/write transactions are zero. - * @author avishnoi@in.ibm.com - * - */ -@SuppressWarnings("rawtypes") -public class StatisticsRequestScheduler implements DataTransactionListener { - - private static final Logger srsLogger = LoggerFactory.getLogger(StatisticsRequestScheduler.class); - private final Timer timer = new Timer("request-monitor", true); - - // We need ordered retrieval, and O(1) contains operation - private final Map requestQueue = - Collections.synchronizedMap(new LinkedHashMap()); - - private Long PendingTransactions; - - private long lastRequestTime = System.nanoTime(); - - private static final long REQUEST_MONITOR_INTERVAL = 1000; - - private final TimerTask task = new TimerTask() { - @Override - public void run() { - try{ - long now = System.nanoTime(); - if(now > lastRequestTime+TimeUnit.MILLISECONDS.toNanos(REQUEST_MONITOR_INTERVAL)){ - requestStatistics(); - } - }catch (IllegalArgumentException | IllegalStateException | NullPointerException e){ - srsLogger.warn("Exception occured while sending statistics request : {}",e); - } - } - }; - - public StatisticsRequestScheduler(){ - PendingTransactions = (long) 0; - } - - public void addRequestToSchedulerQueue(AbstractStatsTracker statsRequest){ - requestQueue.put(statsRequest, null); - } - - public void removeRequestsFromSchedulerQueue(NodeRef node){ - AbstractStatsTracker stats = null; - synchronized(requestQueue){ - Iterator> nodesItr = requestQueue.entrySet().iterator(); - while(nodesItr.hasNext()){ - stats = nodesItr.next().getKey(); - if(stats.getNodeRef().equals(node)){ - nodesItr.remove(); - } - } - } - - } - public AbstractStatsTracker getNextRequestFromSchedulerQueue(){ - //Remove first element - AbstractStatsTracker stats = null; - synchronized(requestQueue){ - Iterator> nodesItr = requestQueue.entrySet().iterator(); - if(nodesItr.hasNext()){ - stats = nodesItr.next().getKey(); - srsLogger.debug("{} chosen up for execution",stats.getNodeRef()); - nodesItr.remove(); - return stats; - } - } - return stats; - } - - private void requestStatistics(){ - AbstractStatsTracker stats = this.getNextRequestFromSchedulerQueue(); - sendStatsRequest(stats); - } - @Override - public void onStatusUpdated(DataModificationTransaction transaction, TransactionStatus status) { - - AbstractStatsTracker stats = null; - synchronized(PendingTransactions){ - switch(status){ - case SUBMITED: - this.PendingTransactions++; - break; - case COMMITED: - case FAILED: - this.PendingTransactions--; - if(PendingTransactions == 0){ - lastRequestTime = System.nanoTime(); - stats = this.getNextRequestFromSchedulerQueue(); - } - srsLogger.debug("Pending MD-SAL transactions : {} & Scheduler queue size : {}",this.PendingTransactions,this.requestQueue.size()); - break; - default: - break; - } - } - sendStatsRequest(stats); - } - - private void sendStatsRequest(AbstractStatsTracker stats){ - if(stats != null){ - try{ - stats.request(); - stats.increaseRequestCounter(); - }catch(Exception e){ - srsLogger.warn("Statistics request was not sent successfully. Reason : {}",e.getMessage()); - } - } - } - public void start(){ - timer.schedule(task, 0, REQUEST_MONITOR_INTERVAL); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractListenCommit.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractListenCommit.java new file mode 100644 index 0000000000..6ebf944b22 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractListenCommit.java @@ -0,0 +1,134 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +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.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatListeningCommiter; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.NotificationListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatAbstractListeneningCommiter + * Class is abstract implementation for all Configuration/DataStore DataChange + * listenable DataObjects like flows, groups, meters. It is a holder for common + * functionality needed by construction/destruction class and for DataChange + * event processing. + * + */ +public abstract class StatAbstractListenCommit + extends StatAbstractNotifyCommit implements StatListeningCommiter { + + private static final Logger LOG = LoggerFactory.getLogger(StatAbstractListenCommit.class); + + private ListenerRegistration listenerRegistration; + + protected final Map, Map, Integer>> mapNodesForDelete = new ConcurrentHashMap<>(); + + private final Class clazz; + + private final DataBroker dataBroker; + + private volatile ReadOnlyTransaction currentReadTx; + + /* Constructor has to make a registration */ + public StatAbstractListenCommit(final StatisticsManager manager, final DataBroker db, + final NotificationProviderService nps, final Class clazz) { + super(manager,nps); + this.clazz = Preconditions.checkNotNull(clazz, "Referenced Class can not be null"); + Preconditions.checkArgument(db != null, "DataBroker can not be null!"); + listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + getWildCardedRegistrationPath(), this, DataChangeScope.BASE); + this.dataBroker = db; + } + + /** + * Method returns WildCarded Path which is used for registration as a listening path changes in + * {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener} + * @return + */ + protected abstract InstanceIdentifier getWildCardedRegistrationPath(); + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> changeEvent) { + Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!"); + /* + * If we have opened read transaction for configuraiton data store, + * we will close and null it. + * + * Latest read transaction will be allocated on another read using readLatestConfiguration + */ + if(currentReadTx != null) { + final ReadOnlyTransaction previous = currentReadTx; + currentReadTx = null; + previous.close(); + } + } + + @SuppressWarnings("unchecked") + protected void removeData(final InstanceIdentifier key, final Integer value) { + if (clazz.equals(key.getTargetType())) { + final InstanceIdentifier nodeIdent = key.firstIdentifierOf(Node.class); + Map, Integer> map = null; + if (mapNodesForDelete.containsKey(nodeIdent)) { + map = mapNodesForDelete.get(nodeIdent); + } + if (map == null) { + map = new ConcurrentHashMap<>(); + mapNodesForDelete.put(nodeIdent, map); + } + map.put((InstanceIdentifier) key, value); + } + } + + @Override + public void close() { + if (listenerRegistration != null) { + try { + listenerRegistration.close(); + } catch (final Exception e) { + LOG.error("Error by stop {} DataChange StatListeningCommiter.", clazz.getSimpleName(), e); + } + listenerRegistration = null; + } + } + + protected final Optional readLatestConfiguration(final InstanceIdentifier path) { + if(currentReadTx == null) { + currentReadTx = dataBroker.newReadOnlyTransaction(); + } + try { + return currentReadTx.read(LogicalDatastoreType.CONFIGURATION, path).checkedGet(); + } catch (final ReadFailedException e) { + return Optional.absent(); + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractNotifyCommit.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractNotifyCommit.java new file mode 100644 index 0000000000..08871e9980 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatAbstractNotifyCommit.java @@ -0,0 +1,134 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.opendaylight.controller.md.statistics.manager.StatNotifyCommiter; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.NotificationListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatAbstratNotifiCommiter + * Class is abstract implementation for all no Configuration/DataStore DataObjects + * and represent common functionality for all DataObject Statistics Commiters. + * Class defines contract between DataObject and relevant Statistics NotificationListener. + * + */ +public abstract class StatAbstractNotifyCommit implements StatNotifyCommiter { + + private static final Logger LOG = LoggerFactory.getLogger(StatAbstractNotifyCommit.class); + + protected final StatisticsManager manager; + private ListenerRegistration notifyListenerRegistration; + + public StatAbstractNotifyCommit(final StatisticsManager manager, + final NotificationProviderService nps) { + Preconditions.checkArgument(nps != null, "NotificationProviderService can not be null!"); + this.manager = Preconditions.checkNotNull(manager, "StatisticManager can not be null!"); + notifyListenerRegistration = nps.registerNotificationListener(getStatNotificationListener()); + } + + @Override + public void close() { + if (notifyListenerRegistration != null) { + try { + notifyListenerRegistration.close(); + } + catch (final Exception e) { + LOG.error("Error by stop {} StatNotificationListener.", this.getClass().getSimpleName()); + } + notifyListenerRegistration = null; + } + } + + /** + * Method returns Statistics Notification Listener for relevant DataObject implementation, + * which is declared for {@link StatNotifyCommiter} interface. + * + * @return + */ + protected abstract N getStatNotificationListener(); + + /** + * PreConfigurationCheck - Node identified by input InstanceIdentifier + * has to be registered in {@link org.opendaylight.controller.md.statistics.manager.StatPermCollector} + * + * @param InstanceIdentifier nodeIdent + */ + protected boolean preConfigurationCheck(final InstanceIdentifier nodeIdent) { + Preconditions.checkNotNull(nodeIdent, "FlowCapableNode ident can not be null!"); + return manager.isProvidedFlowNodeActive(nodeIdent); + } + + protected void notifyToCollectNextStatistics(final InstanceIdentifier nodeIdent) { + Preconditions.checkNotNull(nodeIdent, "FlowCapableNode ident can not be null!"); + manager.collectNextStatistics(nodeIdent); + } + + /** + * Wrapping Future object call for {@link org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager} + * getTransactionCacheContainer with 10sec TimeOut. + * Method has returned {@link Optional} which could contains a {@link TransactionCacheContainer} + * + * @param TransactionId transId + * @param NodeId nodeId + * @return + */ + protected Optional> getTransactionCacheContainer(final TransactionId transId, final NodeId nodeId) { + Optional> txContainer; + try { + txContainer = manager.getRpcMsgManager().getTransactionCacheContainer(transId, nodeId).get(10, TimeUnit.SECONDS); + } + catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Get TransactionCacheContainer fail!", e); + txContainer = Optional.absent(); + } + return txContainer; + } + + /** + * Wrapping Future object call to {@link org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager} + * isExpectedStatistics with 10sec TimeOut. + * Method has checked registration for provided {@link TransactionId} and {@link NodeId} + * + * @param TransactionId transId - Transaction identification + * @param NodeId nodeId - Node identification + * @return boolean + */ + protected boolean isExpectedStatistics(final TransactionId transId, final NodeId nodeId) { + Boolean isExpectedStat = Boolean.FALSE; + try { + isExpectedStat = manager.getRpcMsgManager().isExpectedStatistics(transId, nodeId).get(10, TimeUnit.SECONDS); + } + catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Check Transaction registraion {} fail!", transId, e); + return false; + } + return isExpectedStat.booleanValue(); + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitFlow.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitFlow.java new file mode 100644 index 0000000000..c5aefcbf96 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitFlow.java @@ -0,0 +1,451 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.md.statistics.manager.impl.helper.FlowComparator; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowHashIdMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowHashIdMappingBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowHashIdMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowHashIdMapBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowHashIdMapKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsDataBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatListenCommitFlow + * Class is a NotifyListener for FlowStatistics and DataChangeListener for Config/DataStore for Flow node. + * All expected (registered) FlowStatistics will be builded and commit to Operational/DataStore. + * DataChangeEven should call create/delete Flow in Operational/DS create process needs to pair + * Device Flow HashCode and FlowId from Config/DS + * + * @author Vaclav Demcak + * + */ +public class StatListenCommitFlow extends StatAbstractListenCommit + implements OpendaylightFlowStatisticsListener { + + private static final Logger LOG = LoggerFactory.getLogger(StatListenCommitFlow.class); + + private static final String ALIEN_SYSTEM_FLOW_ID = "#UF$TABLE*"; + + private final AtomicInteger unaccountedFlowsCounter = new AtomicInteger(0); + + public StatListenCommitFlow (final StatisticsManager manager, final DataBroker db, + final NotificationProviderService nps){ + super(manager, db, nps, Flow.class); + } + + @Override + protected OpendaylightFlowStatisticsListener getStatNotificationListener() { + return this; + } + + @Override + protected InstanceIdentifier getWildCardedRegistrationPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class) + .augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class); + } + + @Override + public void onAggregateFlowStatisticsUpdate(final AggregateFlowStatisticsUpdate notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - AggregateFlowStatisticsUpdate: unregistred notification detect TransactionId {}", transId); + return; + } + manager.getRpcMsgManager().addNotification(notification, nodeId); + if (notification.isMoreReplies()) { + return; + } + /* check flow Capable Node and write statistics */ + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (( ! txContainer.isPresent()) || txContainer.get().getNotifications() == null) { + return; + } + final Optional inputObj = txContainer.get().getConfInput(); + if (( ! inputObj.isPresent()) || ( ! (inputObj.get() instanceof Table))) { + return; + } + final Table table = (Table) inputObj.get(); + final List cacheNotifs = txContainer.get().getNotifications(); + for (final TransactionAware notif : cacheNotifs) { + if (notif instanceof AggregateFlowStatisticsUpdate) { + final AggregateFlowStatisticsData stats = new AggregateFlowStatisticsDataBuilder() + .setAggregateFlowStatistics(new AggregateFlowStatisticsBuilder(notification).build()).build(); + final InstanceIdentifier fNodeIdent = InstanceIdentifier.create(Nodes.class) + .child(Node.class, new NodeKey(nodeId)).augmentation(FlowCapableNode.class); + final InstanceIdentifier tableStatRef = fNodeIdent + .child(Table.class, table.getKey()).augmentation(AggregateFlowStatisticsData.class); + Optional fNode = Optional.absent(); + try { + fNode = tx.read(LogicalDatastoreType.OPERATIONAL, fNodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e); + return; + } + if (fNode.isPresent()) { + tx.put(LogicalDatastoreType.OPERATIONAL, tableStatRef, stats, true); + } + } + } + } + }); + } + + @Override + public void onFlowsStatisticsUpdate(final FlowsStatisticsUpdate notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - FlowsStatisticsUpdate: unregistred notification detect TransactionId {}", transId); + return; + } + manager.getRpcMsgManager().addNotification(notification, nodeId); + if (notification.isMoreReplies()) { + LOG.trace("Next notification for join txId {}", transId); + return; + } + /* add flow's statistics */ + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (( ! txContainer.isPresent()) || txContainer.get().getNotifications() == null) { + return; + } + final List flowStats = new ArrayList(10); + final InstanceIdentifier nodeIdent = InstanceIdentifier.create(Nodes.class) + .child(Node.class, new NodeKey(nodeId)); + final List cacheNotifs = txContainer.get().getNotifications(); + for (final TransactionAware notif : cacheNotifs) { + if (notif instanceof FlowsStatisticsUpdate) { + final List notifList = + ((FlowsStatisticsUpdate) notif).getFlowAndStatisticsMapList(); + if (notifList != null) { + flowStats.addAll(notifList); + } + } + } + + statsFlowCommitAll(flowStats, nodeIdent, tx); + /* Notification for continue collecting statistics */ + notifyToCollectNextStatistics(nodeIdent); + } + }); + } + + private void statsFlowCommitAll(final List list, + final InstanceIdentifier nodeIdent, final ReadWriteTransaction tx) { + + final InstanceIdentifier fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class); + + final Optional fNode; + try { + fNode = tx.read(LogicalDatastoreType.OPERATIONAL, fNodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read FlowCapableNode {} in Operational/DS fail! Statistic scan not be updated.", nodeIdent, e); + return; + } + if ( ! fNode.isPresent()) { + LOG.trace("FlowCapableNode {} is not presented in Operational/DS. Statisticscan not be updated.", nodeIdent); + return; + } + + final NodeUpdateState nodeState = new NodeUpdateState(fNodeIdent,fNode.get()); + + for (final FlowAndStatisticsMapList flowStat : list) { + final TableKey tableKey = new TableKey(flowStat.getTableId()); + final TableFlowUpdateState tableState = nodeState.getTable(tableKey, tx); + tableState.reportFlow(flowStat,tx); + } + + for (final TableFlowUpdateState table : nodeState.getTables()) { + table.removeUnreportedFlows(tx); + } + } + + /** + * Method adds statistics to Flow + * + * @param flowBuilder + * @param deviceFlow + */ + private void addStatistics(final FlowBuilder flowBuilder, final FlowAndStatisticsMapList deviceFlow) { + final FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder(deviceFlow); + final FlowStatisticsBuilder flowStatisticsBuilder = new FlowStatisticsBuilder(stats.build()); + final FlowStatisticsDataBuilder flowStatisticsData =new FlowStatisticsDataBuilder(); + flowStatisticsData.setFlowStatistics(flowStatisticsBuilder.build()); + flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build()); + } + + /** + * build pseudoUnique hashCode for flow in table + * for future easy identification + */ + static String buildHashCode(final FlowAndStatisticsMapList deviceFlow) { + final FlowBuilder builder = new FlowBuilder(); + builder.setMatch(deviceFlow.getMatch()); + builder.setCookie(deviceFlow.getCookie()); + builder.setPriority(deviceFlow.getPriority()); + final Flow flowForHashCode = builder.build(); + return String.valueOf(flowForHashCode.hashCode()); + } + + private class NodeUpdateState { + private final InstanceIdentifier nodeIdentifier; + private final Map tables = new HashMap<>(); + + public NodeUpdateState(final InstanceIdentifier fNodeIdent, final FlowCapableNode flowCapableNode) { + nodeIdentifier = fNodeIdent; + final List
tableList = flowCapableNode.getTable(); + if(tableList != null) { + for (final Table table : tableList) { + final TableKey tableKey = table.getKey(); + tables.put(tableKey, new TableFlowUpdateState(nodeIdentifier.child(Table.class,tableKey),table)); + } + } + } + + public Iterable getTables() { + return tables.values(); + } + + TableFlowUpdateState getTable(final TableKey key,final ReadWriteTransaction tx) { + TableFlowUpdateState table = tables.get(key); + if(table == null) { + table = new TableFlowUpdateState(nodeIdentifier.child(Table.class, key), null); + tables.put(key, table); + } + return table; + } + } + + private class TableFlowUpdateState { + private boolean tableEnsured = false; + final KeyedInstanceIdentifier tableRef; + final TableKey tableKey; + final BiMap flowIdByHash; + List configFlows; + + public TableFlowUpdateState(final KeyedInstanceIdentifier tablePath, final Table table) { + tableRef = tablePath; + tableKey = tablePath.getKey(); + flowIdByHash = HashBiMap.create(); + if(table != null) { + final FlowHashIdMapping flowHashMapping = table.getAugmentation(FlowHashIdMapping.class); + if (flowHashMapping != null) { + final List flowHashMap = flowHashMapping.getFlowHashIdMap() != null + ? flowHashMapping.getFlowHashIdMap() : Collections. emptyList(); + for (final FlowHashIdMap flowHashId : flowHashMap) { + flowIdByHash.put(flowHashId.getKey(), flowHashId.getFlowId()); + } + } + } + } + + private void ensureTable(final ReadWriteTransaction tx) { + if( ! tableEnsured) { + final FlowHashIdMapping emptyMapping = new FlowHashIdMappingBuilder() + .setFlowHashIdMap(Collections. emptyList()).build(); + tx.merge(LogicalDatastoreType.OPERATIONAL, tableRef.augmentation(FlowHashIdMapping.class), emptyMapping, true); + tableEnsured = true; + } + } + + private FlowKey searchInConfiguration(final FlowAndStatisticsMapList flowStat, final ReadWriteTransaction trans) { + initConfigFlows(trans); + final Iterator it = configFlows.iterator(); + while(it.hasNext()) { + final Flow cfgFlow = it.next(); + final FlowKey cfgKey = cfgFlow.getKey(); + if(flowIdByHash.inverse().containsKey(cfgKey)) { + it.remove(); + } else if(FlowComparator.flowEquals(flowStat, cfgFlow)) { + it.remove(); + return cfgKey; + } + } + return null; + } + + private void initConfigFlows(final ReadWriteTransaction trans) { + Optional
table = readLatestConfiguration(tableRef); + try { + table = trans.read(LogicalDatastoreType.CONFIGURATION, tableRef).checkedGet(); + } catch (final ReadFailedException e) { + table = Optional.absent(); + } + List localList = null; + if(table.isPresent()) { + localList = table.get().getFlow(); + } + if(localList == null) { + configFlows = Collections.emptyList(); + } else { + configFlows = new LinkedList<>(localList); + } + } + + private FlowKey getFlowKeyAndRemoveHash(final FlowHashIdMapKey key) { + final FlowId ret = flowIdByHash.get(key); + if(ret != null) { + flowIdByHash.remove(key); + return new FlowKey(ret); + } + return null; + } + + /* Returns FlowKey which doesn't exist in any DataStore for now */ + private FlowKey makeAlienFlowKey() { + final StringBuilder sBuilder = new StringBuilder(ALIEN_SYSTEM_FLOW_ID) + .append(tableKey.getId()).append("-").append(unaccountedFlowsCounter.incrementAndGet()); + final FlowId flowId = new FlowId(sBuilder.toString()); + return new FlowKey(flowId); + } + + private Map getRemovalList() { + return flowIdByHash; + } + + void reportFlow(final FlowAndStatisticsMapList flowStat, final ReadWriteTransaction trans) { + ensureTable(trans); + final FlowHashIdMapKey hashingKey = new FlowHashIdMapKey(buildHashCode(flowStat)); + FlowKey flowKey = getFlowKeyAndRemoveHash(hashingKey); + if (flowKey == null) { + flowKey = searchInConfiguration(flowStat, trans); + if ( flowKey == null) { + flowKey = makeAlienFlowKey(); + } + updateHashCache(trans,flowKey,hashingKey); + } + final FlowBuilder flowBuilder = new FlowBuilder(flowStat); + flowBuilder.setKey(flowKey); + addStatistics(flowBuilder, flowStat); + final InstanceIdentifier flowIdent = tableRef.child(Flow.class, flowKey); + trans.put(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build()); + /* check life for Alien flows */ + if (flowKey.getId().getValue().startsWith(ALIEN_SYSTEM_FLOW_ID)) { + removeData(flowIdent, Integer.valueOf(5)); + } + } + + /* Build and deploy new FlowHashId map */ + private void updateHashCache(final ReadWriteTransaction trans, final FlowKey flowKey, final FlowHashIdMapKey hashingKey) { + // TODO Auto-generated method stub + final FlowHashIdMapBuilder flHashIdMap = new FlowHashIdMapBuilder(); + flHashIdMap.setFlowId(flowKey.getId()); + flHashIdMap.setKey(hashingKey); + final KeyedInstanceIdentifier flHashIdent = tableRef + .augmentation(FlowHashIdMapping.class).child(FlowHashIdMap.class, hashingKey); + /* Add new FlowHashIdMap */ + trans.put(LogicalDatastoreType.OPERATIONAL, flHashIdent, flHashIdMap.build()); + } + + void removeUnreportedFlows(final ReadWriteTransaction tx) { + final Map listForRemove = getRemovalList(); + final Optional
configTable = readLatestConfiguration(tableRef); + List configFlows = Collections.emptyList(); + if (configTable.isPresent() && configTable.get().getFlow() != null) { + configFlows = new ArrayList<>(configTable.get().getFlow()); + } + for (final Entry entryForRemove : listForRemove.entrySet()) { + final FlowKey flowKey = new FlowKey(entryForRemove.getValue()); + final InstanceIdentifier flowRef = tableRef.child(Flow.class, flowKey); + final InstanceIdentifier flowStatIdent = flowRef.augmentation(FlowStatisticsData.class); + if (flowKey.getId().getValue().startsWith(ALIEN_SYSTEM_FLOW_ID)) { + final InstanceIdentifier nodeIdent = tableRef.firstIdentifierOf(Node.class); + final Integer lifeIndex = mapNodesForDelete.get(nodeIdent).remove(flowRef); + if (lifeIndex > 0) { + mapNodesForDelete.get(nodeIdent).put(flowRef, Integer.valueOf(lifeIndex.intValue() - 1)); + break; + } + } else { + if (configFlows.remove(flowRef)) { + /* Node is still presented in Config/DataStore - probably lost some multipart msg */ + break; + } + } + final Optional flowStatNodeCheck; + try { + flowStatNodeCheck = tx.read(LogicalDatastoreType.OPERATIONAL, flowStatIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read FlowStatistics {} in Operational/DS fail! Statisticscan not beupdated.", flowStatIdent, e); + break; + } + if (flowStatNodeCheck.isPresent()) { + /* Node isn't new and it has not been removed yet */ + final InstanceIdentifier flHashIdent = tableRef.augmentation(FlowHashIdMapping.class).child(FlowHashIdMap.class, entryForRemove.getKey()); + tx.delete(LogicalDatastoreType.OPERATIONAL, flowRef); + tx.delete(LogicalDatastoreType.OPERATIONAL, flHashIdent); + } + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitGroup.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitGroup.java new file mode 100644 index 0000000000..41d97f080a --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitGroup.java @@ -0,0 +1,296 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStatsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.desc.GroupDescBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatListenCommitGroup + * Class is a NotifyListener for GroupStatistics and DataChangeListener for Config/DataStore for Group node. + * All expected (registered) GroupStatistics will be builded and commit to Operational/DataStore. + * DataChangeEven should call create/delete Group in Operational/DS + * + * @author Vaclav Demcak + * + */ +public class StatListenCommitGroup extends StatAbstractListenCommit + implements OpendaylightGroupStatisticsListener { + + private static final Logger LOG = LoggerFactory.getLogger(StatListenCommitMeter.class); + + public StatListenCommitGroup(final StatisticsManager manager, final DataBroker db, + final NotificationProviderService nps) { + super(manager, db, nps, Group.class); + } + + @Override + protected OpendaylightGroupStatisticsListener getStatNotificationListener() { + return this; + } + + @Override + protected InstanceIdentifier getWildCardedRegistrationPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class) + .augmentation(FlowCapableNode.class).child(Group.class); + } + + @Override + public void onGroupDescStatsUpdated(final GroupDescStatsUpdated notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - GroupDescStatsUpdated: unregistred notification detect TransactionId {}", transId); + return; + } + if (notification.isMoreReplies()) { + manager.getRpcMsgManager().addNotification(notification, nodeId); + return; + } + final List groupStats = notification.getGroupDescStats() != null + ? new ArrayList<>(notification.getGroupDescStats()) : new ArrayList(10); + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (txContainer.isPresent()) { + final List cacheNotifs = + txContainer.get().getNotifications(); + for (final TransactionAware notif : cacheNotifs) { + if (notif instanceof GroupDescStatsUpdated) { + groupStats.addAll(((GroupDescStatsUpdated) notif).getGroupDescStats()); + } + } + } + final InstanceIdentifier nodeIdent = InstanceIdentifier + .create(Nodes.class).child(Node.class, new NodeKey(nodeId)); + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + statGroupDescCommit(groupStats, nodeIdent, tx); + /* Notification for continue collecting statistics */ + notifyToCollectNextStatistics(nodeIdent); + } + }); + } + + @Override + public void onGroupFeaturesUpdated(final GroupFeaturesUpdated notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - MeterFeaturesUpdated: unregistred notification detect TransactionId {}", transId); + return; + } + if (notification.isMoreReplies()) { + manager.getRpcMsgManager().addNotification(notification, nodeId); + return; + } + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if ( ! txContainer.isPresent()) { + return; + } + final InstanceIdentifier nodeIdent = InstanceIdentifier + .create(Nodes.class).child(Node.class, new NodeKey(nodeId)); + + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + notifyToCollectNextStatistics(nodeIdent); + final GroupFeatures stats = new GroupFeaturesBuilder(notification).build(); + final InstanceIdentifier groupFeatureIdent = nodeIdent + .augmentation(NodeGroupFeatures.class).child(GroupFeatures.class); + Optional node = Optional.absent(); + try { + node = tx.read(LogicalDatastoreType.OPERATIONAL, nodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for Node fail! {}", nodeIdent, e); + } + if (node.isPresent()) { + tx.put(LogicalDatastoreType.OPERATIONAL, groupFeatureIdent, stats, true); + } + } + }); + } + + @Override + public void onGroupStatisticsUpdated(final GroupStatisticsUpdated notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - GroupStatisticsUpdated: unregistred notification detect TransactionId {}", transId); + return; + } + if (notification.isMoreReplies()) { + manager.getRpcMsgManager().addNotification(notification, nodeId); + return; + } + final List groupStats = notification.getGroupStats() != null + ? new ArrayList<>(notification.getGroupStats()) : new ArrayList(10); + Optional notifGroup = Optional.absent(); + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (txContainer.isPresent()) { + final Optional inputObj = txContainer.get().getConfInput(); + if (inputObj.isPresent() && inputObj.get() instanceof Group) { + notifGroup = Optional. of((Group)inputObj.get()); + } + final List cacheNotifs = + txContainer.get().getNotifications(); + for (final TransactionAware notif : cacheNotifs) { + if (notif instanceof GroupStatisticsUpdated) { + groupStats.addAll(((GroupStatisticsUpdated) notif).getGroupStats()); + } + } + } + final Optional group = notifGroup; + final InstanceIdentifier nodeIdent = InstanceIdentifier + .create(Nodes.class).child(Node.class, new NodeKey(nodeId)); + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + /* Notification for continue collecting statistics */ + if ( ! group.isPresent()) { + notifyToCollectNextStatistics(nodeIdent); + } + statGroupCommit(groupStats, nodeIdent, group, tx); + } + }); + } + + private void statGroupCommit(final List groupStats, final InstanceIdentifier nodeIdent, + final Optional group, final ReadWriteTransaction trans) { + final InstanceIdentifier fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class); + + for (final GroupStats groupStat : groupStats) { + final GroupStatistics stats = new GroupStatisticsBuilder(groupStat).build(); + + final GroupKey groupKey = new GroupKey(groupStat.getGroupId()); + final InstanceIdentifier gsIdent = fNodeIdent + .child(Group.class,groupKey).augmentation(NodeGroupStatistics.class) + .child(GroupStatistics.class); + /* Statistics Writing */ + Optional fNode = Optional.absent(); + try { + fNode = trans.read(LogicalDatastoreType.OPERATIONAL, fNodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e); + } + if (fNode.isPresent()) { + trans.put(LogicalDatastoreType.OPERATIONAL, gsIdent, stats, true); + } + } + } + + private void statGroupDescCommit(final List groupStats, final InstanceIdentifier nodeIdent, + final ReadWriteTransaction trans) { + final InstanceIdentifier fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class); + + final List deviceGroupKeys = new ArrayList<>(); + + for (final GroupDescStats group : groupStats) { + if (group.getGroupId() != null) { + final GroupBuilder groupBuilder = new GroupBuilder(group); + final GroupKey groupKey = new GroupKey(group.getGroupId()); + final InstanceIdentifier groupRef = fNodeIdent.child(Group.class,groupKey); + + final NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder(); + groupDesc.setGroupDesc(new GroupDescBuilder(group).build()); + //Update augmented data + groupBuilder.addAugmentation(NodeGroupDescStats.class, groupDesc.build()); + deviceGroupKeys.add(groupKey); + Optional hashIdUpd = Optional.absent(); + try { + hashIdUpd = trans.read(LogicalDatastoreType.OPERATIONAL,fNodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e); + } + if (hashIdUpd.isPresent()) { + trans.put(LogicalDatastoreType.OPERATIONAL, groupRef, groupBuilder.build()); + } + } + } + /* Delete all not presented Group Nodes */ + deleteAllNotPresentNode(fNodeIdent, trans, deviceGroupKeys); + } + + private void deleteAllNotPresentNode(final InstanceIdentifier fNodeIdent, + final ReadWriteTransaction trans, final List deviceGroupKeys) { + + final Optional fNode = readLatestConfiguration(fNodeIdent); + if ( ! fNode.isPresent()) { + LOG.trace("Read Operational/DS for FlowCapableNode fail! Node {} doesn't exist.", fNodeIdent); + return; + } + final List existGroups = fNode.get().getGroup().isEmpty() + ? Collections. emptyList() : fNode.get().getGroup(); + /* Add all existed groups paths - no updated paths has to be removed */ + for (final Group group : existGroups) { + if (deviceGroupKeys.remove(group.getKey())) { + break; // group still exist on device + } + LOG.trace("Group {} has to removed.", group); + final InstanceIdentifier delGroupIdent = fNodeIdent.child(Group.class, group.getKey()); + Optional delGroup = Optional.absent(); + try { + delGroup = trans.read(LogicalDatastoreType.OPERATIONAL, delGroupIdent).checkedGet(); + } + catch (final ReadFailedException e) { + // NOOP - probably another transaction delete that node + } + if (delGroup.isPresent()) { + trans.delete(LogicalDatastoreType.OPERATIONAL, delGroupIdent); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitMeter.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitMeter.java new file mode 100644 index 0000000000..e2ae7637c6 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitMeter.java @@ -0,0 +1,283 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStatsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterConfigStatsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatListenCommitMeter + * Class is a NotifyListener for MeterStatistics and DataChangeListener for Config/DataStore for Meter node. + * All expected (registered) MeterStatistics will be builded and commit to Operational/DataStore. + * DataChangeEven should call create/delete Meter in Operational/DS + * + */ +public class StatListenCommitMeter extends StatAbstractListenCommit + implements OpendaylightMeterStatisticsListener { + + private static final Logger LOG = LoggerFactory.getLogger(StatListenCommitMeter.class); + + public StatListenCommitMeter(final StatisticsManager manager, final DataBroker db, + final NotificationProviderService nps) { + super(manager, db, nps, Meter.class); + } + + @Override + protected InstanceIdentifier getWildCardedRegistrationPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class) + .augmentation(FlowCapableNode.class).child(Meter.class); + } + + @Override + protected OpendaylightMeterStatisticsListener getStatNotificationListener() { + return this; + } + + @Override + public void onMeterConfigStatsUpdated(final MeterConfigStatsUpdated notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - MeterConfigStatsUpdated: unregistred notification detect TransactionId {}", transId); + return; + } + if (notification.isMoreReplies()) { + manager.getRpcMsgManager().addNotification(notification, nodeId); + return; + } + final List meterConfStat = notification.getMeterConfigStats() != null + ? new ArrayList<>(notification.getMeterConfigStats()) : new ArrayList(10); + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (txContainer.isPresent()) { + final List cacheNotifs = txContainer.get().getNotifications(); + for (final TransactionAware notif : cacheNotifs) { + if (notif instanceof MeterConfigStatsUpdated) { + meterConfStat.addAll(((MeterConfigStatsUpdated) notif).getMeterConfigStats()); + } + } + } + final InstanceIdentifier nodeIdent = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(nodeId)); + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + /* Notification for continue collecting statistics */ + notifyToCollectNextStatistics(nodeIdent); + comitConfMeterStats(meterConfStat, nodeIdent, tx); + } + }); + } + + @Override + public void onMeterFeaturesUpdated(final MeterFeaturesUpdated notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - MeterFeaturesUpdated: unregistred notification detect TransactionId {}", transId); + return; + } + if (notification.isMoreReplies()) { + manager.getRpcMsgManager().addNotification(notification, nodeId); + return; + } + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if ( ! txContainer.isPresent()) { + return; + } + final MeterFeatures stats = new MeterFeaturesBuilder(notification).build(); + final InstanceIdentifier nodeIdent = InstanceIdentifier + .create(Nodes.class).child(Node.class, new NodeKey(nodeId)); + final InstanceIdentifier meterFeatureIdent = nodeIdent + .augmentation(NodeMeterFeatures.class).child(MeterFeatures.class); + + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + /* Notification for continue collecting statistics */ + notifyToCollectNextStatistics(nodeIdent); + Optional node = Optional.absent(); + try { + node = tx.read(LogicalDatastoreType.OPERATIONAL, nodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for Node fail! {}", nodeIdent, e); + } + if (node.isPresent()) { + tx.put(LogicalDatastoreType.OPERATIONAL, meterFeatureIdent, stats, true); + } + } + }); + } + + @Override + public void onMeterStatisticsUpdated(final MeterStatisticsUpdated notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - MeterStatisticsUpdated: unregistred notification detect TransactionId {}", transId); + return; + } + if (notification.isMoreReplies()) { + manager.getRpcMsgManager().addNotification(notification, nodeId); + return; + } + final List meterStat = notification.getMeterStats() != null + ? new ArrayList<>(notification.getMeterStats()) : new ArrayList(10); + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (txContainer.isPresent()) { + final List cacheNotifs = txContainer.get().getNotifications(); + for (final TransactionAware notif : cacheNotifs) { + if (notif instanceof MeterConfigStatsUpdated) { + meterStat.addAll(((MeterStatisticsUpdated) notif).getMeterStats()); + } + } + } + final InstanceIdentifier nodeIdent = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(nodeId)); + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + statMeterCommit(meterStat, nodeIdent, tx); + /* Notification for continue collecting statistics */ + notifyToCollectNextStatistics(nodeIdent); + } + }); + } + + private void statMeterCommit(final List meterStats, + final InstanceIdentifier nodeIdent, final ReadWriteTransaction trans) { + + final InstanceIdentifier fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class); + for (final MeterStats mStat : meterStats) { + final MeterStatistics stats = new MeterStatisticsBuilder(mStat).build(); + + final MeterKey mKey = new MeterKey(mStat.getMeterId()); + final InstanceIdentifier msIdent = fNodeIdent + .child(Meter.class, mKey).augmentation(NodeMeterStatistics.class) + .child(MeterStatistics.class); + /* Meter Statistics commit */ + Optional fNode = Optional.absent(); + try { + fNode = trans.read(LogicalDatastoreType.OPERATIONAL, fNodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e); + } + if (fNode.isPresent()) { + trans.put(LogicalDatastoreType.OPERATIONAL, msIdent, stats, true); + } + } + } + + private void comitConfMeterStats(final List meterConfStat, + final InstanceIdentifier nodeIdent, final ReadWriteTransaction trans) { + + final InstanceIdentifier fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class); + final List deviceMeterKeys = new ArrayList<>(); + + for (final MeterConfigStats meterConf : meterConfStat) { + final MeterBuilder meterBuilder = new MeterBuilder(meterConf); + if (meterConf.getMeterId() != null) { + final MeterKey meterKey = new MeterKey(meterConf.getMeterId()); + meterBuilder.setKey(meterKey); + final InstanceIdentifier meterRef = nodeIdent + .augmentation(FlowCapableNode.class).child(Meter.class,meterKey); + final NodeMeterConfigStatsBuilder meterConfig = new NodeMeterConfigStatsBuilder(); + meterConfig.setMeterConfigStats(new MeterConfigStatsBuilder(meterConf).build()); + //Update augmented data + meterBuilder.addAugmentation(NodeMeterConfigStats.class, meterConfig.build()); + deviceMeterKeys.add(meterKey); + Optional fNode = Optional.absent(); + try { + fNode = trans.read(LogicalDatastoreType.OPERATIONAL, fNodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e); + } + if (fNode.isPresent()) { + trans.put(LogicalDatastoreType.OPERATIONAL, meterRef, meterBuilder.build()); + } + } + } + /* Delete all not presented Meter Nodes */ + deleteAllNotPresentedNodes(fNodeIdent, trans, deviceMeterKeys); + } + + private void deleteAllNotPresentedNodes(final InstanceIdentifier fNodeIdent, + final ReadWriteTransaction trans, final List deviceMeterKeys) { + /* Delete all not presented meters */ + final Optional fNode = readLatestConfiguration(fNodeIdent); + + if ( ! fNode.isPresent()) { + LOG.trace("Read Operational/DS for FlowCapableNode fail! Node {} doesn't exist.", fNodeIdent); + return; + } + final List existMeters = fNode.get().getMeter().isEmpty() + ? Collections. emptyList() : fNode.get().getMeter(); + /* Add all existed groups paths - no updated paths has to be removed */ + for (final Meter meter : existMeters) { + if (deviceMeterKeys.remove(meter.getKey())) { + break; // Meter still exist on device + } + final InstanceIdentifier delMeterIdent = fNodeIdent.child(Meter.class, meter.getKey()); + Optional delMeter = Optional.absent(); + try { + delMeter = trans.read(LogicalDatastoreType.OPERATIONAL, delMeterIdent).checkedGet(); + } + catch (final ReadFailedException e) { + // NOOP - probably another transaction delete that node + } + if (delMeter.isPresent()) { + trans.delete(LogicalDatastoreType.OPERATIONAL, delMeterIdent); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java new file mode 100644 index 0000000000..29fe5d8e5e --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java @@ -0,0 +1,149 @@ +/** + * 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.md.statistics.manager.impl; + +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.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsDataBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdate; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatistics; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatNotifyCommitQueue + * Class is a NotifyListner for Queues Statistics + * All expected (registered) queueStatistics will be builded and + * commit to Operational/DataStore + * + * @author Vaclav Demcak + * + */ +public class StatListenCommitQueue extends StatAbstractListenCommit + implements OpendaylightQueueStatisticsListener { + + private final static Logger LOG = LoggerFactory.getLogger(StatListenCommitQueue.class); + + public StatListenCommitQueue(final StatisticsManager manager, final DataBroker db, + final NotificationProviderService nps) { + super(manager, db, nps, Queue.class); + } + + @Override + protected OpendaylightQueueStatisticsListener getStatNotificationListener() { + return this; + } + + @Override + protected InstanceIdentifier getWildCardedRegistrationPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class) + .augmentation(FlowCapableNodeConnector.class).child(Queue.class); + } + + @Override + public void onQueueStatisticsUpdate(final QueueStatisticsUpdate notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - QueueStatisticsUpdate: unregistred notification detect TransactionId {}", transId); + return; + } + if (notification.isMoreReplies()) { + manager.getRpcMsgManager().addNotification(notification, nodeId); + return; + } + final List queueStats = notification.getQueueIdAndStatisticsMap() != null + ? new ArrayList<>(notification.getQueueIdAndStatisticsMap()) : new ArrayList(10); + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (txContainer.isPresent()) { + final List cachedNotifs = + txContainer.get().getNotifications(); + for (final TransactionAware notif : cachedNotifs) { + if (notif instanceof QueueStatisticsUpdate) { + queueStats.addAll(((QueueStatisticsUpdate) notif).getQueueIdAndStatisticsMap()); + } + } + } + final InstanceIdentifier nodeIdent = InstanceIdentifier.create(Nodes.class) + .child(Node.class, new NodeKey(nodeId)); + /* Queue statistics are small size and we are not able to change for OF cross controller + * - don't need to make are atomic */ + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction trans) { + /* Notification for continue */ + notifyToCollectNextStatistics(nodeIdent); + statQueueCommit(queueStats, nodeIdent, trans); + } + }); + } + + private void statQueueCommit(final List queueStats, + final InstanceIdentifier nodeIdent, final ReadWriteTransaction trans) { + + /* check exist FlowCapableNode and write statistics */ + Optional fNode = Optional.absent(); + try { + fNode = trans.read(LogicalDatastoreType.OPERATIONAL, nodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for Node fail! {}", nodeIdent, e); + return; + } + if ( ! fNode.isPresent()) { + LOG.trace("Read Operational/DS for Node fail! Node {} doesn't exist.", nodeIdent); + return; + } + + for (final QueueIdAndStatisticsMap queueEntry : queueStats) { + final FlowCapableNodeConnectorQueueStatistics statChild = + new FlowCapableNodeConnectorQueueStatisticsBuilder(queueEntry).build(); + final FlowCapableNodeConnectorQueueStatisticsDataBuilder statBuild = + new FlowCapableNodeConnectorQueueStatisticsDataBuilder(); + statBuild.setFlowCapableNodeConnectorQueueStatistics(statChild); + final QueueKey qKey = new QueueKey(queueEntry.getQueueId()); + final InstanceIdentifier queueStatIdent = nodeIdent + .child(NodeConnector.class, new NodeConnectorKey(queueEntry.getNodeConnectorId())) + .augmentation(FlowCapableNodeConnector.class) + .child(Queue.class, qKey).augmentation(FlowCapableNodeConnectorQueueStatisticsData.class); + trans.put(LogicalDatastoreType.OPERATIONAL, queueStatIdent, statBuild.build(), true); + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNodeRegistrationImpl.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNodeRegistrationImpl.java new file mode 100644 index 0000000000..adb5870986 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNodeRegistrationImpl.java @@ -0,0 +1,207 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +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.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatNodeRegistration; +import org.opendaylight.controller.md.statistics.manager.StatPermCollector.StatCapabTypes; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityGroupStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatNodeRegistrationImpl + * {@link FlowCapableNode} Registration Implementation contains two method for registration/unregistration + * {@link FeatureCapability} for every connect/disconnect {@link FlowCapableNode}. Process of connection/disconnection + * is substituted by listening Operation/DS for add/delete {@link FeatureCapability}. + * All statistic capabilities are reading from new Node directly without contacting device or DS. + * + * @author Vaclav Demcak + * + * Created: Aug 28, 2014 + */ +public class StatNodeRegistrationImpl implements StatNodeRegistration { + + private static final Logger LOG = LoggerFactory.getLogger(StatNodeRegistrationImpl.class); + + private final StatisticsManager manager; + private ListenerRegistration listenerRegistration; + private ListenerRegistration notifListenerRegistration; + + public StatNodeRegistrationImpl(final StatisticsManager manager, final DataBroker db, + final NotificationProviderService notificationService) { + this.manager = Preconditions.checkNotNull(manager, "StatisticManager can not be null!"); + Preconditions.checkArgument(db != null, "DataBroker can not be null!"); + Preconditions.checkArgument(notificationService != null, "NotificationProviderService can not be null!"); + notifListenerRegistration = notificationService.registerNotificationListener(this); + } + + @Override + public void close() throws Exception { + + if (notifListenerRegistration != null) { + try { + notifListenerRegistration.close(); + } + catch (final Exception e) { + LOG.warn("Error by stop FlowCapableNode Notification StatNodeRegistration."); + } + notifListenerRegistration = null; + } + + if (listenerRegistration != null) { + try { + listenerRegistration.close(); + } catch (final Exception e) { + LOG.warn("Error by stop FlowCapableNode DataChange StatListeningCommiter.", e); + } + listenerRegistration = null; + } + } + + @Override + public void connectFlowCapableNode(final InstanceIdentifier keyIdent, + final SwitchFeatures data, final InstanceIdentifier nodeIdent) { + Preconditions.checkNotNull(keyIdent, "InstanceIdentifier can not be null!"); + Preconditions.checkNotNull(data, "SwitchFeatures data for {} can not be null!", keyIdent); + Preconditions.checkArgument(( ! keyIdent.isWildcarded()), "InstanceIdentifier is WildCarded!"); + + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + + final List statCapabTypes = new ArrayList<>(); + Short maxCapTables = Short.valueOf("1"); + + final List> capabilities = data.getCapabilities() != null + ? data.getCapabilities() : Collections.> emptyList(); + for (final Class capability : capabilities) { + if (capability == FlowFeatureCapabilityTableStats.class) { + statCapabTypes.add(StatCapabTypes.TABLE_STATS); + } else if (capability == FlowFeatureCapabilityFlowStats.class) { + statCapabTypes.add(StatCapabTypes.FLOW_STATS); + } else if (capability == FlowFeatureCapabilityGroupStats.class) { + statCapabTypes.add(StatCapabTypes.GROUP_STATS); + } else if (capability == FlowFeatureCapabilityPortStats.class) { + statCapabTypes.add(StatCapabTypes.PORT_STATS); + } else if (capability == FlowFeatureCapabilityQueueStats.class) { + statCapabTypes.add(StatCapabTypes.QUEUE_STATS); + } + } + maxCapTables = data.getMaxTables(); + + final Optional maxTables = Optional. of(maxCapTables); + + /* Meters management */ + final InstanceIdentifier meterFeaturesIdent = nodeIdent.augmentation(NodeMeterFeatures.class); + + + Optional meterFeatures = Optional.absent(); + try { + meterFeatures = tx.read(LogicalDatastoreType.OPERATIONAL, meterFeaturesIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.warn("Read NodeMeterFeatures {} fail!", meterFeaturesIdent, e); + } + if (meterFeatures.isPresent()) { + statCapabTypes.add(StatCapabTypes.METER_STATS); + } + manager.connectedNodeRegistration(nodeIdent, + Collections.unmodifiableList(statCapabTypes), maxTables.get()); + } + }); + } + + @Override + public void disconnectFlowCapableNode(final InstanceIdentifier nodeIdent) { + Preconditions.checkArgument(nodeIdent != null, "InstanceIdentifier can not be NULL!"); + Preconditions.checkArgument(( ! nodeIdent.isWildcarded()), + "InstanceIdentifier {} is WildCarded!", nodeIdent); + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction tx) { + manager.disconnectedNodeUnregistration(nodeIdent); + } + }); + } + + + @Override + public void onNodeConnectorRemoved(final NodeConnectorRemoved notification) { + // NOOP + } + + @Override + public void onNodeConnectorUpdated(final NodeConnectorUpdated notification) { + // NOOP + } + + @Override + public void onNodeRemoved(final NodeRemoved notification) { + final NodeRef nodeRef = notification.getNodeRef(); + final InstanceIdentifier nodeRefIdent = nodeRef.getValue(); + final InstanceIdentifier nodeIdent = + nodeRefIdent.firstIdentifierOf(Node.class); + if (nodeIdent != null) { + disconnectFlowCapableNode(nodeIdent); + } + } + + @Override + public void onNodeUpdated(final NodeUpdated notification) { + final FlowCapableNodeUpdated newFlowNode = + notification.getAugmentation(FlowCapableNodeUpdated.class); + if (newFlowNode != null && newFlowNode.getSwitchFeatures() != null) { + final NodeRef nodeRef = notification.getNodeRef(); + final InstanceIdentifier nodeRefIdent = nodeRef.getValue(); + final InstanceIdentifier nodeIdent = + nodeRefIdent.firstIdentifierOf(Node.class); + + final InstanceIdentifier swichFeaturesIdent = + nodeIdent.augmentation(FlowCapableNode.class).child(SwitchFeatures.class); + final SwitchFeatures switchFeatures = newFlowNode.getSwitchFeatures(); + connectFlowCapableNode(swichFeaturesIdent, switchFeatures, nodeIdent); + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitPort.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitPort.java new file mode 100644 index 0000000000..72c10ee316 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitPort.java @@ -0,0 +1,148 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatNotifyCommitPort + * Class is a NotifyListener for PortStatistics + * All expected (registered) portStatistics will be builded and + * commit to Operational/DataStore + * + * @author Vaclav Demcak + * + */ +public class StatNotifyCommitPort extends StatAbstractNotifyCommit + implements OpendaylightPortStatisticsListener { + + private static final Logger LOG = LoggerFactory.getLogger(StatNotifyCommitPort.class); + + public StatNotifyCommitPort(final StatisticsManager manager, + final NotificationProviderService nps) { + super(manager, nps); + } + + @Override + protected OpendaylightPortStatisticsListener getStatNotificationListener() { + return this; + } + + @Override + public void onNodeConnectorStatisticsUpdate(final NodeConnectorStatisticsUpdate notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - NodeConnectorStatisticsUpdate: unregistred notification detect TransactionId {}", transId); + return; + } + manager.getRpcMsgManager().addNotification(notification, nodeId); + if (notification.isMoreReplies()) { + return; + } + final InstanceIdentifier nodeIdent = InstanceIdentifier.create(Nodes.class) + .child(Node.class, new NodeKey(nodeId)); + /* Don't block RPC Notification thread */ + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction trans) { + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + if (( ! txContainer.isPresent()) || txContainer.get().getNotifications() == null) { + return; + } + final List portStats = + new ArrayList(10); + final List cachedNotifs = txContainer.get().getNotifications(); + for (final TransactionAware notif : cachedNotifs) { + if (notif instanceof NodeConnectorStatisticsUpdate) { + final List notifStat = + ((NodeConnectorStatisticsUpdate) notif).getNodeConnectorStatisticsAndPortNumberMap(); + if (notifStat != null) { + portStats.addAll(notifStat); + } + } + } + /* write stat to trans */ + statPortCommit(portStats, nodeIdent, trans); + /* Notification for continue collecting statistics - Port statistics are still same size + * and they are small - don't need to wait for whole apply operation*/ + notifyToCollectNextStatistics(nodeIdent); + } + }); + } + + private void statPortCommit(final List portStats, + final InstanceIdentifier nodeIdent, final ReadWriteTransaction tx) { + + /* check exist FlowCapableNode and write statistics probable with parent */ + Optional fNode = Optional.absent(); + try { + fNode = tx.read(LogicalDatastoreType.OPERATIONAL, nodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for Node fail! {}", nodeIdent, e); + return; + } + if ( ! fNode.isPresent()) { + LOG.trace("Read Operational/DS for Node fail! Node {} doesn't exist.", nodeIdent); + return; + } + for (final NodeConnectorStatisticsAndPortNumberMap nConnectPort : portStats) { + final FlowCapableNodeConnectorStatisticsData stats = new FlowCapableNodeConnectorStatisticsDataBuilder() + .setFlowCapableNodeConnectorStatistics(new FlowCapableNodeConnectorStatisticsBuilder(nConnectPort).build()).build(); + final NodeConnectorKey key = new NodeConnectorKey(nConnectPort.getNodeConnectorId()); + final InstanceIdentifier nodeConnectorIdent = nodeIdent.child(NodeConnector.class, key); + final InstanceIdentifier nodeConnStatIdent = nodeConnectorIdent + .augmentation(FlowCapableNodeConnectorStatisticsData.class); + Optional fNodeConector; + try { + fNodeConector = tx.read(LogicalDatastoreType.OPERATIONAL, nodeConnectorIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read NodeConnector {} in Operational/DS fail!", nodeConnectorIdent, e); + fNodeConector = Optional.absent(); + } + if (fNodeConector.isPresent()) { + tx.put(LogicalDatastoreType.OPERATIONAL, nodeConnStatIdent, stats); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitTable.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitTable.java new file mode 100644 index 0000000000..3210934f88 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatNotifyCommitTable.java @@ -0,0 +1,138 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager.TransactionCacheContainer; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsDataBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatNotifyCommitTable + * Class is a NotifyListener for TableStatistics + * All expected (registered) tableStatistics will be builded and + * commit to Operational/DataStore + * + * @author Vaclav Demcak + * + */ +public class StatNotifyCommitTable extends StatAbstractNotifyCommit + implements OpendaylightFlowTableStatisticsListener { + + private final static Logger LOG = LoggerFactory.getLogger(StatNotifyCommitTable.class); + + public StatNotifyCommitTable(final StatisticsManager manager, + final NotificationProviderService nps) { + super(manager, nps); + } + + @Override + protected OpendaylightFlowTableStatisticsListener getStatNotificationListener() { + return this; + } + + @Override + public void onFlowTableStatisticsUpdate(final FlowTableStatisticsUpdate notification) { + final TransactionId transId = notification.getTransactionId(); + final NodeId nodeId = notification.getId(); + if ( ! isExpectedStatistics(transId, nodeId)) { + LOG.debug("STAT-MANAGER - FlowTableStatisticsUpdate: unregistred notification detect TransactionId {}", transId); + return; + } + manager.getRpcMsgManager().addNotification(notification, nodeId); + if (notification.isMoreReplies()) { + return; + } + /* Don't block RPC Notification thread */ + manager.enqueue(new StatDataStoreOperation() { + @Override + public void applyOperation(final ReadWriteTransaction trans) { + final List tableStats = new ArrayList(10); + final Optional> txContainer = getTransactionCacheContainer(transId, nodeId); + final InstanceIdentifier nodeIdent = InstanceIdentifier.create(Nodes.class) + .child(Node.class, new NodeKey(nodeId)); + if (( ! txContainer.isPresent()) || txContainer.get().getNodeId() == null) { + return; + } + final List cachedNotifs = txContainer.get().getNotifications(); + for (final TransactionAware notif : cachedNotifs) { + if (notif instanceof FlowTableStatisticsUpdate) { + final List statNotif = + ((FlowTableStatisticsUpdate) notif).getFlowTableAndStatisticsMap(); + if (statNotif != null) { + tableStats.addAll(statNotif); + } + } + } + /* write stat to trans */ + statTableCommit(tableStats, nodeIdent, trans); + /* Notification for continue collecting statistics - Tables statistics are still same size + * and they are small - don't need to wait to whole apply operation */ + notifyToCollectNextStatistics(nodeIdent); + } + }); + } + + private void statTableCommit(final List tableStats, final InstanceIdentifier nodeIdent, + final ReadWriteTransaction trans) { + final InstanceIdentifier fNodeIdent = nodeIdent.augmentation(FlowCapableNode.class); + /* check flow Capable Node and write statistics */ + Optional fNode = Optional.absent(); + try { + fNode = trans.read(LogicalDatastoreType.OPERATIONAL, fNodeIdent).checkedGet(); + } + catch (final ReadFailedException e) { + LOG.debug("Read Operational/DS for FlowCapableNode fail! {}", fNodeIdent, e); + return; + } + if ( ! fNode.isPresent()) { + LOG.trace("Read Operational/DS for FlowCapableNode fail! Node {} doesn't exist.", fNodeIdent); + return; + } + for (final FlowTableAndStatisticsMap tableStat : tableStats) { + final FlowTableStatisticsData stats = new FlowTableStatisticsDataBuilder() + .setFlowTableStatistics(new FlowTableStatisticsBuilder(tableStat).build()).build(); + + final InstanceIdentifier tStatIdent = fNodeIdent + .child(Table.class, new TableKey(tableStat.getTableId().getValue())) + .augmentation(FlowTableStatisticsData.class); + trans.put(LogicalDatastoreType.OPERATIONAL, tStatIdent, stats, true); + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatPermCollectorImpl.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatPermCollectorImpl.java new file mode 100644 index 0000000000..d008042e8d --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatPermCollectorImpl.java @@ -0,0 +1,305 @@ +package org.opendaylight.controller.md.statistics.manager.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +import org.opendaylight.controller.md.statistics.manager.StatPermCollector; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatPermCollectorImpl + * Thread base statistic collector. Class holds internal map for all registered + * (means connected) nodes with List of Switch capabilities; + * Statistics collecting process get cross whole Network Device by device + * and statistic by statistic (follow Switch capabilities to prevent unnecessary + * ask) Next statistic start collecting by notification or by timeout. + * + * @author @author avishnoi@in.ibm.com Vaclav Demcak + * + */ +public class StatPermCollectorImpl implements StatPermCollector { + + private final static Logger LOG = LoggerFactory.getLogger(StatPermCollectorImpl.class); + + private final static long STAT_COLLECT_TIME_OUT = 30000L; + + private final ExecutorService statNetCollectorServ; + private final StatisticsManager manager; + + private final int maxNodeForCollector; + private final long minReqNetInterval; + private final String name; + + private final Object statCollectorLock = new Object(); + private final Object statNodeHolderLock = new Object(); + + private Map, StatNodeInfoHolder> statNodeHolder = + Collections., StatNodeInfoHolder> emptyMap(); + + private volatile boolean wakeMe = false; + private volatile boolean finishing = false; + + public StatPermCollectorImpl(final StatisticsManager manager, final long minReqNetInterv, final int nr, + final int maxNodeForCollectors) { + this.manager = Preconditions.checkNotNull(manager, "StatisticsManager can not be null!"); + name = "odl-stat-collector-" + nr; + minReqNetInterval = minReqNetInterv; + final ThreadFactory threadFact = new ThreadFactoryBuilder() + .setNameFormat(name + "-thread-%d").build(); + statNetCollectorServ = Executors.newSingleThreadExecutor(threadFact); + maxNodeForCollector = maxNodeForCollectors; + LOG.trace("StatCollector {} start successfull!", name); + } + + /** + * finish collecting statistics + */ + @Override + public void close() { + statNodeHolder = Collections., StatNodeInfoHolder> emptyMap(); + finishing = true; + collectNextStatistics(); + statNetCollectorServ.shutdown(); + } + + @Override + public boolean isProvidedFlowNodeActive( + final InstanceIdentifier flowNode) { + return statNodeHolder.containsKey(flowNode); + } + + @Override + public boolean connectedNodeRegistration(final InstanceIdentifier ident, + final List statTypes, final Short nrOfSwitchTables) { + if (ident.isWildcarded()) { + LOG.warn("FlowCapableNode IstanceIdentifier {} registration can not be wildcarded!", ident); + } else { + if ( ! statNodeHolder.containsKey(ident)) { + synchronized (statNodeHolderLock) { + final boolean startStatCollecting = statNodeHolder.size() == 0; + if ( ! statNodeHolder.containsKey(ident)) { + if (statNodeHolder.size() >= maxNodeForCollector) { + return false; + } + final Map, StatNodeInfoHolder> statNode = + new HashMap<>(statNodeHolder); + final NodeRef nodeRef = new NodeRef(ident); + final StatNodeInfoHolder nodeInfoHolder = new StatNodeInfoHolder(nodeRef, + statTypes, nrOfSwitchTables); + statNode.put(ident, nodeInfoHolder); + statNodeHolder = Collections.unmodifiableMap(statNode); + } + if (startStatCollecting) { + finishing = false; + statNetCollectorServ.execute(this); + } + } + } + } + return true; + } + + @Override + public boolean disconnectedNodeUnregistration(final InstanceIdentifier ident) { + if (ident.isWildcarded()) { + LOG.warn("FlowCapableNode IstanceIdentifier {} unregistration can not be wildcarded!", ident); + } else { + if (statNodeHolder.containsKey(ident)) { + synchronized (statNodeHolderLock) { + if (statNodeHolder.containsKey(ident)) { + final Map, StatNodeInfoHolder> statNode = + new HashMap<>(statNodeHolder); + statNode.remove(ident); + statNodeHolder = Collections.unmodifiableMap(statNode); + } + if (statNodeHolder.isEmpty()) { + finishing = true; + collectNextStatistics(); + statNetCollectorServ.shutdown(); + } + return true; + } + } + } + return false; + } + + @Override + public void collectNextStatistics() { + if (wakeMe) { + synchronized (statCollectorLock) { + if (wakeMe) { + LOG.trace("STAT-COLLECTOR is notified to conntinue"); + statCollectorLock.notify(); + } + } + } + } + + @Override + public void run() { + try { + Thread.sleep(5000); + } + catch (final InterruptedException e1) { + // NOOP + } + LOG.debug("StatCollector {} Start collecting!", name); + /* Neverending cyle - wait for finishing */ + while ( ! finishing) { + boolean collecting = false; + final long startTime = System.currentTimeMillis(); + + if ( ! statNodeHolder.isEmpty()) { + collecting = true; + collectStatCrossNetwork(); + collecting = false; + } + + if ( ! collecting) { + final long statFinalTime = System.currentTimeMillis() - startTime; + LOG.debug("STAT-MANAGER {}: last all NET statistics collection cost {} ms", name, statFinalTime); + if (statFinalTime < minReqNetInterval) { + LOG.trace("statCollector is about to make a collecting sleep"); + synchronized (statCollectorLock) { + wakeMe = true; + try { + final long waitTime = minReqNetInterval - statFinalTime; + statCollectorLock.wait(waitTime); + LOG.trace("STAT-MANAGER : statCollector {} is waking up from a collecting sleep for {} ms", name, waitTime); + } catch (final InterruptedException e) { + LOG.warn("statCollector has been interrupted during collecting sleep", e); + } finally { + wakeMe = false; + } + } + } + } + } + } + + private void waitingForNotification() { + synchronized (statCollectorLock) { + wakeMe = true; + try { + statCollectorLock.wait(STAT_COLLECT_TIME_OUT); + LOG.trace("statCollector is waking up from a wait stat Response sleep"); + } catch (final InterruptedException e) { + LOG.warn("statCollector has been interrupted waiting stat Response sleep", e); + } finally { + wakeMe = false; + } + } + } + + + private void collectStatCrossNetwork() { + for (final Entry, StatNodeInfoHolder> nodeEntity : statNodeHolder.entrySet()) { + final List listNeededStat = nodeEntity.getValue().getStatMarkers(); + final NodeRef actualNodeRef = nodeEntity.getValue().getNodeRef(); + final Short maxTables = nodeEntity.getValue().getMaxTables(); + for (final StatCapabTypes statMarker : listNeededStat) { + if ( ! isProvidedFlowNodeActive(nodeEntity.getKey())) { + break; + } + switch (statMarker) { + case PORT_STATS: + LOG.trace("STAT-MANAGER-collecting PORT-STATS for NodeRef {}", actualNodeRef); + manager.getRpcMsgManager().getAllPortsStat(actualNodeRef); + waitingForNotification(); + break; + case QUEUE_STATS: + LOG.trace("STAT-MANAGER-collecting QUEUE-STATS for NodeRef {}", actualNodeRef); + manager.getRpcMsgManager().getAllQueueStat(actualNodeRef); + waitingForNotification(); + break; + case TABLE_STATS: + LOG.trace("STAT-MANAGER-collecting TABLE-STATS for NodeRef {}", actualNodeRef); + manager.getRpcMsgManager().getAllTablesStat(actualNodeRef); + waitingForNotification(); + break; + case GROUP_STATS: + LOG.trace("STAT-MANAGER-collecting GROUP-STATS for NodeRef {}", actualNodeRef); + manager.getRpcMsgManager().getGroupFeaturesStat(actualNodeRef); + waitingForNotification(); + manager.getRpcMsgManager().getAllGroupsConfStats(actualNodeRef); + waitingForNotification(); + manager.getRpcMsgManager().getAllGroupsStat(actualNodeRef); + waitingForNotification(); + break; + case METER_STATS: + LOG.trace("STAT-MANAGER-collecting METER-STATS for NodeRef {}", actualNodeRef); + manager.getRpcMsgManager().getMeterFeaturesStat(actualNodeRef); + waitingForNotification(); + manager.getRpcMsgManager().getAllMeterConfigStat(actualNodeRef); + waitingForNotification(); + manager.getRpcMsgManager().getAllMetersStat(actualNodeRef); + waitingForNotification(); + break; + case FLOW_STATS: + LOG.trace("STAT-MANAGER-collecting FLOW-STATS-ALL_FLOWS for NodeRef {}", actualNodeRef); + manager.getRpcMsgManager().getAllFlowsStat(actualNodeRef); + waitingForNotification(); + LOG.trace("STAT-MANAGER-collecting FLOW-AGGREGATE-STATS for NodeRef {}", actualNodeRef); + for (short i = 0; i < maxTables; i++) { + final TableId tableId = new TableId(i); + manager.getRpcMsgManager().getAggregateFlowStat(actualNodeRef, tableId); + } + break; + default: + /* Exception for programmers in implementation cycle */ + throw new IllegalStateException("Not implemented ASK for " + statMarker); + } + } + } + } + + private class StatNodeInfoHolder { + private final NodeRef nodeRef; + private final List statMarkers; + private final Short maxTables; + + public StatNodeInfoHolder(final NodeRef nodeRef, + final List statMarkers, final Short maxTables) { + this.nodeRef = nodeRef; + this.maxTables = maxTables; + this.statMarkers = statMarkers; + } + + public final NodeRef getNodeRef() { + return nodeRef; + } + + public final List getStatMarkers() { + return statMarkers; + } + + public final Short getMaxTables() { + return maxTables; + } + } + + @Override + public boolean hasActiveNodes() { + return ( ! statNodeHolder.isEmpty()); + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/RPCFailedException.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatRPCFailedException.java similarity index 75% rename from opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/RPCFailedException.java rename to opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatRPCFailedException.java index 308c6ddebe..5ff4913cc0 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/RPCFailedException.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatRPCFailedException.java @@ -5,17 +5,17 @@ * 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.md.statistics.manager; - -import java.util.Collection; +package org.opendaylight.controller.md.statistics.manager.impl; import org.opendaylight.yangtools.yang.common.RpcError; -final class RPCFailedException extends RuntimeException { +import java.util.Collection; + +public final class StatRPCFailedException extends RuntimeException { private static final long serialVersionUID = 1L; private final Collection errors; - public RPCFailedException(final String message, final Collection errors) { + public StatRPCFailedException(final String message, final Collection errors) { super(message); this.errors = errors; } diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatRpcMsgManagerImpl.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatRpcMsgManagerImpl.java new file mode 100644 index 0000000000..8058554840 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatRpcMsgManagerImpl.java @@ -0,0 +1,517 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager.StatDataStoreOperation; +import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.JdkFutureAdapters; +import com.google.common.util.concurrent.SettableFuture; + + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager.impl + * + * StatRpcMsgManagerImpl + * Class register and provide all RPC Statistics Device Services and implement pre-defined + * wrapped methods for prepare easy access to RPC Statistics Device Services like getAllStatisticsFor... + * + * In next Class implement process for joining multipart messages. + * Class internally use two WeakHashMap and GuavaCache for holding values for joining multipart msg. + * One Weak map is used for holding all Multipart Messages and second is used for possible input + * Config/DS light-weight DataObject (DataObject contains only necessary identification fields as + * TableId, GroupId, MeterId or for flow Match, Priority, FlowCookie, TableId and FlowId ... + * + * @author avishnoi@in.ibm.com Vaclav Demcak + * + */ +public class StatRpcMsgManagerImpl implements StatRpcMsgManager { + + private final static Logger LOG = LoggerFactory.getLogger(StatRpcMsgManagerImpl.class); + + private final Cache> txCache; + + private final long maxLifeForRequest = 50; /* 50 second */ + private final int queueCapacity = 5000; + private final StatisticsManager manager; + + private final OpendaylightGroupStatisticsService groupStatsService; + private final OpendaylightMeterStatisticsService meterStatsService; + private final OpendaylightFlowStatisticsService flowStatsService; + private final OpendaylightPortStatisticsService portStatsService; + private final OpendaylightFlowTableStatisticsService flowTableStatsService; + private final OpendaylightQueueStatisticsService queueStatsService; + + private BlockingQueue statsRpcJobQueue; + + private volatile boolean finishing = false; + + public StatRpcMsgManagerImpl (final StatisticsManager manager, + final RpcConsumerRegistry rpcRegistry, final long minReqNetMonitInt) { + this.manager = Preconditions.checkNotNull(manager, "StatisticManager can not be null!"); + Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !"); + groupStatsService = Preconditions.checkNotNull( + rpcRegistry.getRpcService(OpendaylightGroupStatisticsService.class), + "OpendaylightGroupStatisticsService can not be null!"); + meterStatsService = Preconditions.checkNotNull( + rpcRegistry.getRpcService(OpendaylightMeterStatisticsService.class), + "OpendaylightMeterStatisticsService can not be null!"); + flowStatsService = Preconditions.checkNotNull( + rpcRegistry.getRpcService(OpendaylightFlowStatisticsService.class), + "OpendaylightFlowStatisticsService can not be null!"); + portStatsService = Preconditions.checkNotNull( + rpcRegistry.getRpcService(OpendaylightPortStatisticsService.class), + "OpendaylightPortStatisticsService can not be null!"); + flowTableStatsService = Preconditions.checkNotNull( + rpcRegistry.getRpcService(OpendaylightFlowTableStatisticsService.class), + "OpendaylightFlowTableStatisticsService can not be null!"); + queueStatsService = Preconditions.checkNotNull( + rpcRegistry.getRpcService(OpendaylightQueueStatisticsService.class), + "OpendaylightQueueStatisticsService can not be null!"); + + statsRpcJobQueue = new LinkedBlockingQueue<>(queueCapacity); + txCache = CacheBuilder.newBuilder().expireAfterWrite(maxLifeForRequest, TimeUnit.SECONDS) + .maximumSize(10000).build(); + } + + @Override + public void close() { + finishing = true; + statsRpcJobQueue = null; + } + + @Override + public void run() { + /* Neverending cyle - wait for finishing */ + while ( ! finishing) { + try { + statsRpcJobQueue.take().call(); + } + catch (final Exception e) { + LOG.warn("Stat Element RPC executor fail!", e); + } + } + // Drain all rpcCall, making sure any blocked threads are unblocked + while ( ! statsRpcJobQueue.isEmpty()) { + statsRpcJobQueue.poll(); + } + } + + private void addGetAllStatJob(final RpcJobsQueue getAllStatJob) { + final boolean success = statsRpcJobQueue.offer(getAllStatJob); + if ( ! success) { + LOG.warn("Put RPC request getAllStat fail! Queue is full."); + } + } + + private void addStatJob(final RpcJobsQueue getStatJob) { + final boolean success = statsRpcJobQueue.offer(getStatJob); + if ( ! success) { + LOG.debug("Put RPC request for getStat fail! Queue is full."); + } + } + + @Override + public void registrationRpcFutureCallBack( + final Future> future, final D inputObj, final NodeRef nodeRef) { + + Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), + new FutureCallback>() { + + @Override + public void onSuccess(final RpcResult result) { + final TransactionId id = result.getResult().getTransactionId(); + if (id == null) { + LOG.warn("No protocol support"); + } else { + final NodeKey nodeKey = nodeRef.getValue().firstKeyOf(Node.class, NodeKey.class); + final String cacheKey = buildCacheKey(id, nodeKey.getId()); + final TransactionCacheContainer container = + new TransactionCacheContainerImpl<>(id, inputObj, nodeKey.getId()); + txCache.put(cacheKey, container); + } + } + + @Override + public void onFailure(final Throwable t) { + LOG.warn("Response Registration for Statistics RPC call fail!", t); + } + + }); + } + + private String buildCacheKey(final TransactionId id, final NodeId nodeId) { + return String.valueOf(id.getValue()) + "-" + nodeId.getValue(); + } + + @Override + public Future>> getTransactionCacheContainer( + final TransactionId id, final NodeId nodeId) { + Preconditions.checkArgument(id != null, "TransactionId can not be null!"); + Preconditions.checkArgument(nodeId != null, "NodeId can not be null!"); + + final String key = buildCacheKey(id, nodeId); + final SettableFuture>> result = SettableFuture.create(); + + final RpcJobsQueue getTransactionCacheContainer = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final Optional> resultContainer = + Optional.> fromNullable(txCache.getIfPresent(key)); + if (resultContainer.isPresent()) { + txCache.invalidate(key); + } + result.set(resultContainer); + return null; + } + }; + addStatJob(getTransactionCacheContainer); + return result; + } + + @Override + public Future isExpectedStatistics(final TransactionId id, final NodeId nodeId) { + Preconditions.checkArgument(id != null, "TransactionId can not be null!"); + Preconditions.checkArgument(nodeId != null, "NodeId can not be null!"); + + final String key = buildCacheKey(id, nodeId); + final SettableFuture checkStatId = SettableFuture.create(); + + final RpcJobsQueue isExpecedStatistics = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final Optional> result = + Optional.> fromNullable(txCache.getIfPresent(key)); + checkStatId.set(Boolean.valueOf(result.isPresent())); + return null; + } + }; + addStatJob(isExpecedStatistics); + return checkStatId; + } + + @Override + public void addNotification(final TransactionAware notification, final NodeId nodeId) { + Preconditions.checkArgument(notification != null, "TransactionAware can not be null!"); + Preconditions.checkArgument(nodeId != null, "NodeId can not be null!"); + + final RpcJobsQueue addNotification = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final TransactionId txId = notification.getTransactionId(); + final String key = buildCacheKey(txId, nodeId); + final TransactionCacheContainer container = (txCache.getIfPresent(key)); + if (container != null) { + container.addNotif(notification); + } + return null; + } + }; + addStatJob(addNotification); + } + + @Override + public void getAllGroupsStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getAllGroupStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final GetAllGroupStatisticsInputBuilder builder = + new GetAllGroupStatisticsInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(groupStatsService + .getAllGroupStatistics(builder.build()), null, nodeRef); + return null; + } + }; + addGetAllStatJob(getAllGroupStat); + } + + @Override + public void getAllMetersStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getAllMeterStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final GetAllMeterStatisticsInputBuilder builder = + new GetAllMeterStatisticsInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(meterStatsService + .getAllMeterStatistics(builder.build()), null, nodeRef); + return null; + } + }; + addGetAllStatJob(getAllMeterStat); + } + + @Override + public void getAllFlowsStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getAllFlowStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder builder = + new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(flowStatsService + .getAllFlowsStatisticsFromAllFlowTables(builder.build()), null, nodeRef); + return null; + } + }; + addGetAllStatJob(getAllFlowStat); + } + + @Override + public void getAggregateFlowStat(final NodeRef nodeRef, final TableId tableId) { + + manager.enqueue(new StatDataStoreOperation() { + + @Override + public void applyOperation(final ReadWriteTransaction tx) { + final RpcJobsQueue getAggregateFlowStat = new RpcJobsQueue() { + @Override + public Void call() throws Exception { + final GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder builder = + new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder(); + builder.setNode(nodeRef); + builder.setTableId(tableId); + + final TableBuilder tbuilder = new TableBuilder(); + tbuilder.setId(tableId.getValue()); + tbuilder.setKey(new TableKey(tableId.getValue())); + registrationRpcFutureCallBack(flowStatsService + .getAggregateFlowStatisticsFromFlowTableForAllFlows(builder.build()), tbuilder.build(), nodeRef); + return null; + } + }; + addGetAllStatJob(getAggregateFlowStat); + } + }); + } + + @Override + public void getAllPortsStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getAllPortsStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final GetAllNodeConnectorsStatisticsInputBuilder builder = + new GetAllNodeConnectorsStatisticsInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(portStatsService + .getAllNodeConnectorsStatistics(builder.build()), null, nodeRef); + return null; + } + }; + addGetAllStatJob(getAllPortsStat); + } + + @Override + public void getAllTablesStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getAllTableStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final GetFlowTablesStatisticsInputBuilder builder = + new GetFlowTablesStatisticsInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(flowTableStatsService + .getFlowTablesStatistics(builder.build()), null, nodeRef); + return null; + } + }; + addGetAllStatJob(getAllTableStat); + } + + @Override + public void getAllQueueStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getAllQueueStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final GetAllQueuesStatisticsFromAllPortsInputBuilder builder = + new GetAllQueuesStatisticsFromAllPortsInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(queueStatsService + .getAllQueuesStatisticsFromAllPorts(builder.build()), null, nodeRef); + return null; + } + }; + addGetAllStatJob(getAllQueueStat); + } + + @Override + public void getAllMeterConfigStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue qetAllMeterConfStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + final GetAllMeterConfigStatisticsInputBuilder builder = + new GetAllMeterConfigStatisticsInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(meterStatsService + .getAllMeterConfigStatistics(builder.build()), null, nodeRef); + return null; + } + }; + addGetAllStatJob(qetAllMeterConfStat); + } + + @Override + public void getGroupFeaturesStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getGroupFeaturesStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + /* RPC input */ + final GetGroupFeaturesInputBuilder input = new GetGroupFeaturesInputBuilder(); + input.setNode(nodeRef); + registrationRpcFutureCallBack(groupStatsService.getGroupFeatures(input.build()), null, nodeRef); + return null; + } + }; + addStatJob(getGroupFeaturesStat); + } + + @Override + public void getMeterFeaturesStat(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getMeterFeaturesStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + /* RPC input */ + final GetMeterFeaturesInputBuilder input = new GetMeterFeaturesInputBuilder(); + input.setNode(nodeRef); + registrationRpcFutureCallBack(meterStatsService.getMeterFeatures(input.build()), null, nodeRef); + return null; + } + }; + addStatJob(getMeterFeaturesStat); + } + + @Override + public void getAllGroupsConfStats(final NodeRef nodeRef) { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final RpcJobsQueue getAllGropConfStat = new RpcJobsQueue() { + + @Override + public Void call() throws Exception { + Preconditions.checkArgument(nodeRef != null, "NodeRef can not be null!"); + final GetGroupDescriptionInputBuilder builder = + new GetGroupDescriptionInputBuilder(); + builder.setNode(nodeRef); + registrationRpcFutureCallBack(groupStatsService + .getGroupDescription(builder.build()), null, nodeRef); + + return null; + } + }; + addGetAllStatJob(getAllGropConfStat); + } + + public class TransactionCacheContainerImpl implements TransactionCacheContainer { + + private final TransactionId id; + private final NodeId nId; + private final List notifications; + private final Optional confInput; + + public TransactionCacheContainerImpl (final TransactionId id, final D input, final NodeId nodeId) { + this.id = Preconditions.checkNotNull(id, "TransactionId can not be null!"); + notifications = new CopyOnWriteArrayList(); + confInput = Optional.fromNullable(input); + nId = nodeId; + } + + @Override + public void addNotif(final T notif) { + notifications.add(notif); + } + + @Override + public TransactionId getId() { + return id; + } + + @Override + public NodeId getNodeId() { + return nId; + } + + @Override + public List getNotifications() { + return notifications; + } + + @Override + public Optional getConfInput() { + return confInput; + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java new file mode 100644 index 0000000000..8430549be1 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java @@ -0,0 +1,358 @@ +/** + * 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.md.statistics.manager.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadFactory; + +import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction; +import org.opendaylight.controller.md.sal.common.api.data.TransactionChain; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.controller.md.statistics.manager.StatListeningCommiter; +import org.opendaylight.controller.md.statistics.manager.StatNodeRegistration; +import org.opendaylight.controller.md.statistics.manager.StatNotifyCommiter; +import org.opendaylight.controller.md.statistics.manager.StatPermCollector; +import org.opendaylight.controller.md.statistics.manager.StatPermCollector.StatCapabTypes; +import org.opendaylight.controller.md.statistics.manager.StatRpcMsgManager; +import org.opendaylight.controller.md.statistics.manager.StatisticsManager; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsListener; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +/** +* statistics-manager +* org.opendaylight.controller.md.statistics.manager.impl +* +* StatisticsManagerImpl +* It represent a central point for whole module. Implementation +* {@link StatisticsManager} registers all Operation/DS {@link StatNotifyCommiter} and +* Config/DS {@StatListeningCommiter}, as well as {@link StatPermCollector} +* for statistic collecting and {@link StatRpcMsgManager} as Device RPCs provider. +* In next, StatisticsManager provides all DS contact Transaction services. +* +* @author avishnoi@in.ibm.com Vaclav Demcak +* +*/ +public class StatisticsManagerImpl implements StatisticsManager, Runnable { + + private final static Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class); + + private static final int QUEUE_DEPTH = 500; + private static final int MAX_BATCH = 1; + + private final BlockingQueue dataStoreOperQueue = new LinkedBlockingDeque<>(QUEUE_DEPTH); + + private final DataBroker dataBroker; + private final int maxNodesForCollectors; + private long minReqNetMonitInt; + private final ExecutorService statRpcMsgManagerExecutor; + private final ExecutorService statDataStoreOperationServ; + private StatRpcMsgManager rpcMsgManager; + private List statCollectors; + private final Object statCollectorLock = new Object(); + private BindingTransactionChain txChain; + private volatile boolean finishing = false; + + private StatNodeRegistration nodeRegistrator; + private StatListeningCommiter flowListeningCommiter; + private StatListeningCommiter meterListeningCommiter; + private StatListeningCommiter groupListeningCommiter; + private StatListeningCommiter queueNotifyCommiter; + private StatNotifyCommiter tableNotifCommiter; + private StatNotifyCommiter portNotifyCommiter; + + public StatisticsManagerImpl (final DataBroker dataBroker, final int maxNodesForCollector) { + this.dataBroker = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!"); + ThreadFactory threadFact; + threadFact = new ThreadFactoryBuilder().setNameFormat("odl-stat-rpc-oper-thread-%d").build(); + statRpcMsgManagerExecutor = Executors.newSingleThreadExecutor(threadFact); + threadFact = new ThreadFactoryBuilder().setNameFormat("odl-stat-ds-oper-thread-%d").build(); + statDataStoreOperationServ = Executors.newSingleThreadExecutor(threadFact); + maxNodesForCollectors = maxNodesForCollector; + txChain = dataBroker.createTransactionChain(this); + } + + @Override + public void start(final NotificationProviderService notifService, + final RpcConsumerRegistry rpcRegistry, final long minReqNetMonitInt) { + Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !"); + this.minReqNetMonitInt = minReqNetMonitInt; + rpcMsgManager = new StatRpcMsgManagerImpl(this, rpcRegistry, minReqNetMonitInt); + statCollectors = Collections.emptyList(); + nodeRegistrator = new StatNodeRegistrationImpl(this, dataBroker, notifService); + flowListeningCommiter = new StatListenCommitFlow(this, dataBroker, notifService); + meterListeningCommiter = new StatListenCommitMeter(this, dataBroker, notifService); + groupListeningCommiter = new StatListenCommitGroup(this, dataBroker, notifService); + tableNotifCommiter = new StatNotifyCommitTable(this, notifService); + portNotifyCommiter = new StatNotifyCommitPort(this, notifService); + queueNotifyCommiter = new StatListenCommitQueue(this, dataBroker, notifService); + + statRpcMsgManagerExecutor.execute(rpcMsgManager); + statDataStoreOperationServ.execute(this); + LOG.info("Statistics Manager started successfully!"); + } + + @Override + public void close() throws Exception { + finishing = true; + if (nodeRegistrator != null) { + nodeRegistrator.close(); + nodeRegistrator = null; + } + if (flowListeningCommiter != null) { + flowListeningCommiter.close(); + flowListeningCommiter = null; + } + if (meterListeningCommiter != null) { + meterListeningCommiter.close(); + meterListeningCommiter = null; + } + if (groupListeningCommiter != null) { + groupListeningCommiter.close(); + groupListeningCommiter = null; + } + if (tableNotifCommiter != null) { + tableNotifCommiter.close(); + tableNotifCommiter = null; + } + if (portNotifyCommiter != null) { + portNotifyCommiter.close(); + portNotifyCommiter = null; + } + if (queueNotifyCommiter != null) { + queueNotifyCommiter.close(); + queueNotifyCommiter = null; + } + if (statCollectors != null) { + for (StatPermCollector collector : statCollectors) { + collector.close(); + collector = null; + } + statCollectors = null; + } + if (rpcMsgManager != null) { + rpcMsgManager.close(); + rpcMsgManager = null; + } + statRpcMsgManagerExecutor.shutdown(); + statDataStoreOperationServ.shutdown(); + if (txChain != null) { + txChain.close(); + txChain = null; + } + } + + @Override + public void enqueue(final StatDataStoreOperation op) { + // we don't need to block anything - next statistics come soon + final boolean success = dataStoreOperQueue.offer(op); + if ( ! success) { + LOG.debug("Stat DS/Operational submiter Queue is full!"); + } + } + + @Override + public void run() { + /* Neverending cyle - wait for finishing */ + while ( ! finishing) { + try { + StatDataStoreOperation op = dataStoreOperQueue.take(); + final ReadWriteTransaction tx = txChain.newReadWriteTransaction(); + LOG.trace("New operations available, starting transaction {}", tx.getIdentifier()); + + int ops = 0; + do { + op.applyOperation(tx); + + ops++; + if (ops < MAX_BATCH) { + op = dataStoreOperQueue.poll(); + } else { + op = null; + } + } while (op != null); + + LOG.trace("Processed {} operations, submitting transaction {}", ops, tx.getIdentifier()); + + try { + tx.submit().checkedGet(); + } catch (final TransactionCommitFailedException e) { + LOG.warn("Stat DataStoreOperation unexpected State!", e); + txChain.close(); + txChain = dataBroker.createTransactionChain(StatisticsManagerImpl.this); + cleanDataStoreOperQueue(); + } + } + catch (final IllegalStateException e) { + LOG.warn("Stat DataStoreOperation unexpected State!", e); + } + catch (final InterruptedException e) { + LOG.warn("Stat Manager DS Operation thread interupted!", e); + finishing = true; + } + catch (final Exception e) { + LOG.warn("Stat DataStore Operation executor fail!", e); + } + } + // Drain all events, making sure any blocked threads are unblocked + cleanDataStoreOperQueue(); + } + + private void cleanDataStoreOperQueue() { + // Drain all events, making sure any blocked threads are unblocked + while (! dataStoreOperQueue.isEmpty()) { + dataStoreOperQueue.poll(); + } + } + + @Override + public void onTransactionChainFailed(final TransactionChain chain, final AsyncTransaction transaction, + final Throwable cause) { + LOG.warn("Failed to export Flow Capable Statistics, Transaction {} failed.",transaction.getIdentifier(),cause); + txChain.close(); + txChain = dataBroker.createTransactionChain(StatisticsManagerImpl.this); + cleanDataStoreOperQueue(); + } + + @Override + public void onTransactionChainSuccessful(final TransactionChain chain) { + // NOOP + } + + @Override + public boolean isProvidedFlowNodeActive(final InstanceIdentifier nodeIdent) { + for (final StatPermCollector collector : statCollectors) { + if (collector.isProvidedFlowNodeActive(nodeIdent)) { + return true; + } + } + return false; + } + + @Override + public void collectNextStatistics(final InstanceIdentifier nodeIdent) { + for (final StatPermCollector collector : statCollectors) { + if (collector.isProvidedFlowNodeActive(nodeIdent)) { + collector.collectNextStatistics(); + } + } + } + + @Override + public void connectedNodeRegistration(final InstanceIdentifier nodeIdent, + final List statTypes, final Short nrOfSwitchTables) { + for (final StatPermCollector collector : statCollectors) { + if (collector.connectedNodeRegistration(nodeIdent, statTypes, nrOfSwitchTables)) { + return; + } + } + synchronized (statCollectorLock) { + for (final StatPermCollector collector : statCollectors) { + if (collector.connectedNodeRegistration(nodeIdent, statTypes, nrOfSwitchTables)) { + return; + } + } + final StatPermCollectorImpl newCollector = new StatPermCollectorImpl(this, + minReqNetMonitInt, statCollectors.size() + 1, maxNodesForCollectors); + final List statCollectorsNew = new ArrayList<>(statCollectors); + newCollector.connectedNodeRegistration(nodeIdent, statTypes, nrOfSwitchTables); + statCollectorsNew.add(newCollector); + statCollectors = Collections.unmodifiableList(statCollectorsNew); + } + } + + @Override + public void disconnectedNodeUnregistration(final InstanceIdentifier nodeIdent) { + for (final StatPermCollector collector : statCollectors) { + if (collector.disconnectedNodeUnregistration(nodeIdent)) { + if ( ! collector.hasActiveNodes()) { + synchronized (statCollectorLock) { + if (collector.hasActiveNodes()) { + return; + } + final List newStatColl = + new ArrayList<>(statCollectors); + newStatColl.remove(collector); + statCollectors = Collections.unmodifiableList(newStatColl); + } + } + return; + } + } + LOG.debug("Node {} has not removed.", nodeIdent); + } + + /* Getter internal Statistic Manager Job Classes */ + @Override + public StatRpcMsgManager getRpcMsgManager() { + return rpcMsgManager; + } + + @Override + public StatNodeRegistration getNodeRegistrator() { + return nodeRegistrator; + } + + @Override + public StatListeningCommiter getFlowListenComit() { + return flowListeningCommiter; + } + + @Override + public StatListeningCommiter getMeterListenCommit() { + return meterListeningCommiter; + } + + @Override + public StatListeningCommiter getGroupListenCommit() { + return groupListeningCommiter; + } + + @Override + public StatListeningCommiter getQueueNotifyCommit() { + return queueNotifyCommiter; + } + + + @Override + public StatNotifyCommiter getTableNotifCommit() { + return tableNotifCommiter; + } + + @Override + public StatNotifyCommiter getPortNotifyCommit() { + return portNotifyCommiter; + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/helper/FlowComparator.java similarity index 80% rename from opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java rename to opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/helper/FlowComparator.java index f3dac826e8..c6205cb13c 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/helper/FlowComparator.java @@ -5,15 +5,14 @@ * 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.md.statistics.manager; +package org.opendaylight.controller.md.statistics.manager.impl.helper; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.net.InetAddresses; import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.UnknownHostException; - import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch; @@ -22,19 +21,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.annotations.VisibleForTesting; - /** * Utility class for comparing flows. */ -final class FlowComparator { - private final static Logger logger = LoggerFactory.getLogger(FlowComparator.class); +public final class FlowComparator { + private final static Logger LOG = LoggerFactory.getLogger(FlowComparator.class); private FlowComparator() { - + throw new UnsupportedOperationException("Utilities class should not be instantiated"); } - public static boolean flowEquals(Flow statsFlow, Flow storedFlow) { + public static boolean flowEquals(final Flow statsFlow, final Flow storedFlow) { if (statsFlow == null || storedFlow == null) { return false; } @@ -93,7 +90,7 @@ final class FlowComparator { * @param storedFlow * @return */ - public static boolean matchEquals(Match statsFlow, Match storedFlow) { + public static boolean matchEquals(final Match statsFlow, final Match storedFlow) { if (statsFlow == storedFlow) { return true; } @@ -194,9 +191,9 @@ final class FlowComparator { * statistic data, openflow driver library returns AA:BB:CC:DD:EE:FF and default eqauls fails here. */ @VisibleForTesting - static boolean ethernetMatchEquals(EthernetMatch statsEthernetMatch, EthernetMatch storedEthernetMatch){ + static boolean ethernetMatchEquals(final EthernetMatch statsEthernetMatch, final EthernetMatch storedEthernetMatch){ boolean verdict = true; - Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch); + final Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch); if (checkNullValues != null) { verdict = checkNullValues; } else { @@ -219,10 +216,10 @@ final class FlowComparator { return verdict; } - private static boolean ethernetMatchFieldsEquals(MacAddressFilter statsEthernetMatchFields, - MacAddressFilter storedEthernetMatchFields){ + private static boolean ethernetMatchFieldsEquals(final MacAddressFilter statsEthernetMatchFields, + final MacAddressFilter storedEthernetMatchFields){ boolean verdict = true; - Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields); + final Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields); if (checkNullValues != null) { verdict = checkNullValues; } else { @@ -236,9 +233,9 @@ final class FlowComparator { return verdict; } - private static boolean macAddressEquals(MacAddress statsMacAddress, MacAddress storedMacAddress){ + private static boolean macAddressEquals(final MacAddress statsMacAddress, final MacAddress storedMacAddress){ boolean verdict = true; - Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress); + final Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress); if (checkNullValues != null) { verdict = checkNullValues; } else { @@ -248,11 +245,11 @@ final class FlowComparator { } @VisibleForTesting - static boolean layer3MatchEquals(Layer3Match statsLayer3Match, Layer3Match storedLayer3Match){ + static boolean layer3MatchEquals(final Layer3Match statsLayer3Match, final Layer3Match storedLayer3Match){ boolean verdict = true; if(statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4Match){ - Ipv4Match statsIpv4Match = (Ipv4Match)statsLayer3Match; - Ipv4Match storedIpv4Match = (Ipv4Match)storedLayer3Match; + final Ipv4Match statsIpv4Match = (Ipv4Match)statsLayer3Match; + final Ipv4Match storedIpv4Match = (Ipv4Match)storedLayer3Match; if (verdict) { verdict = compareNullSafe( @@ -263,7 +260,7 @@ final class FlowComparator { statsIpv4Match.getIpv4Source(), storedIpv4Match.getIpv4Source()); } } else { - Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match); + final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match); if (nullCheckOut != null) { verdict = nullCheckOut; } else { @@ -274,9 +271,9 @@ final class FlowComparator { return verdict; } - private static boolean compareNullSafe(Ipv4Prefix statsIpv4, Ipv4Prefix storedIpv4) { + private static boolean compareNullSafe(final Ipv4Prefix statsIpv4, final Ipv4Prefix storedIpv4) { boolean verdict = true; - Boolean checkDestNullValuesOut = checkNullValues(storedIpv4, statsIpv4); + final Boolean checkDestNullValuesOut = checkNullValues(storedIpv4, statsIpv4); if (checkDestNullValuesOut != null) { verdict = checkDestNullValuesOut; } else if(!IpAddressEquals(statsIpv4, storedIpv4)){ @@ -286,7 +283,7 @@ final class FlowComparator { return verdict; } - private static Boolean checkNullValues(Object v1, Object v2) { + private static Boolean checkNullValues(final Object v1, final Object v2) { Boolean verdict = null; if (v1 == null && v2 != null) { verdict = Boolean.FALSE; @@ -306,9 +303,9 @@ final class FlowComparator { * @param storedIpAddress * @return true if IPv4prefixes equals */ - private static boolean IpAddressEquals(Ipv4Prefix statsIpAddress, Ipv4Prefix storedIpAddress) { - IntegerIpAddress statsIpAddressInt = StrIpToIntIp(statsIpAddress.getValue()); - IntegerIpAddress storedIpAddressInt = StrIpToIntIp(storedIpAddress.getValue()); + private static boolean IpAddressEquals(final Ipv4Prefix statsIpAddress, final Ipv4Prefix storedIpAddress) { + final IntegerIpAddress statsIpAddressInt = StrIpToIntIp(statsIpAddress.getValue()); + final IntegerIpAddress storedIpAddressInt = StrIpToIntIp(storedIpAddress.getValue()); if(IpAndMaskBasedMatch(statsIpAddressInt,storedIpAddressInt)){ return true; @@ -319,11 +316,11 @@ final class FlowComparator { return false; } - private static boolean IpAndMaskBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){ + private static boolean IpAndMaskBasedMatch(final IntegerIpAddress statsIpAddressInt,final IntegerIpAddress storedIpAddressInt){ return ((statsIpAddressInt.getIp() & statsIpAddressInt.getMask()) == (storedIpAddressInt.getIp() & storedIpAddressInt.getMask())); } - private static boolean IpBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){ + private static boolean IpBasedMatch(final IntegerIpAddress statsIpAddressInt,final IntegerIpAddress storedIpAddressInt){ return (statsIpAddressInt.getIp() == storedIpAddressInt.getIp()); } @@ -331,10 +328,10 @@ final class FlowComparator { * Method return integer version of ip address. Converted int will be mask if * mask specified */ - private static IntegerIpAddress StrIpToIntIp(String ipAddresss){ + private static IntegerIpAddress StrIpToIntIp(final String ipAddresss){ - String[] parts = ipAddresss.split("/"); - String ip = parts[0]; + final String[] parts = ipAddresss.split("/"); + final String ip = parts[0]; int prefix; if (parts.length < 2) { @@ -344,20 +341,19 @@ final class FlowComparator { } IntegerIpAddress integerIpAddress = null; - try { - Inet4Address addr = (Inet4Address) InetAddress.getByName(ip); - byte[] addrBytes = addr.getAddress(); - int ipInt = ((addrBytes[0] & 0xFF) << 24) | + + final Inet4Address addr = ((Inet4Address) InetAddresses.forString(ip)); + final byte[] addrBytes = addr.getAddress(); + final int ipInt = ((addrBytes[0] & 0xFF) << 24) | ((addrBytes[1] & 0xFF) << 16) | ((addrBytes[2] & 0xFF) << 8) | ((addrBytes[3] & 0xFF) << 0); - int mask = 0xffffffff << 32 - prefix; + // FIXME: Is this valid? + final int mask = 0xffffffff << 32 - prefix; integerIpAddress = new IntegerIpAddress(ipInt, mask); - } catch (UnknownHostException e){ - logger.error("Failed to determine host IP address by name: {}", e.getMessage(), e); - } + return integerIpAddress; } @@ -365,7 +361,7 @@ final class FlowComparator { private static class IntegerIpAddress{ int ip; int mask; - public IntegerIpAddress(int ip, int mask) { + public IntegerIpAddress(final int ip, final int mask) { this.ip = ip; this.mask = mask; } diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java b/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java new file mode 100644 index 0000000000..6a01cd2c26 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java @@ -0,0 +1,39 @@ +/** + * 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.md.statistics.manager; + +/** + * statistics-manager + * org.opendaylight.controller.md.statistics.manager + * + * + * + * @author Vaclav Demcak + * + * Created: Sep 6, 2014 + */ +public class StatisticsManagerProvider { + + private final StatisticsManagerActivator activator; + + public StatisticsManagerProvider(final StatisticsManagerActivator activator) { + this.activator = activator; + } + + /** + * Method provides Initialized {@link StatisticsManager} + * from {@link StatisticsManagerActivator} for all tests + * suites; + * + * @return + */ + public StatisticsManager getStatisticsManager() { + return activator.getStatisticManager(); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/impl/helper/StatisticsUpdateCommiterTest.java similarity index 81% rename from opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java rename to opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/impl/helper/StatisticsUpdateCommiterTest.java index a687b1f280..9361e281e9 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/impl/helper/StatisticsUpdateCommiterTest.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.md.statistics.manager; +package org.opendaylight.controller.md.statistics.manager.impl.helper; import org.junit.Assert; import org.junit.Test; @@ -35,7 +35,7 @@ public class StatisticsUpdateCommiterTest { */ @Test public void testLayer3MatchEquals() { - String[][][] matchSeeds = new String[][][] { + final String[][][] matchSeeds = new String[][][] { {{"10.1.2.0/24", "10.1.2.0/24"}, {"10.1.2.0/24", "10.1.2.0/24"}}, {{"10.1.2.0/24", "10.1.2.0/24"}, {"10.1.2.0/24", "10.1.1.0/24"}}, {{"10.1.1.0/24", "10.1.2.0/24"}, {"10.1.2.0/24", "10.1.2.0/24"}}, @@ -55,7 +55,7 @@ public class StatisticsUpdateCommiterTest { {{null, null}, {null, null}}, }; - boolean[] matches = new boolean[] { + final boolean[] matches = new boolean[] { true, false, false, @@ -91,23 +91,23 @@ public class StatisticsUpdateCommiterTest { * @param matches expected match output * */ - private static void checkComparisonOfL3Match(String m1Source, String m1Destination, - String m2Source, String msDestination, boolean matches) { - Ipv4Match m1Layer3 = prepareIPv4Match(m1Source, m1Destination); - Ipv4Match m2Layer3 = prepareIPv4Match(m2Source, msDestination); + private static void checkComparisonOfL3Match(final String m1Source, final String m1Destination, + final String m2Source, final String msDestination, final boolean matches) { + final Ipv4Match m1Layer3 = prepareIPv4Match(m1Source, m1Destination); + final Ipv4Match m2Layer3 = prepareIPv4Match(m2Source, msDestination); boolean comparisonResult; try { comparisonResult = FlowComparator.layer3MatchEquals(m1Layer3, m2Layer3); Assert.assertEquals("failed to compare: "+m1Layer3+" vs. "+m2Layer3, matches, comparisonResult); - } catch (Exception e) { + } catch (final Exception e) { LOG.error("failed to compare: {} vs. {}", m1Layer3, m2Layer3, e); Assert.fail(e.getMessage()); } } - private static Ipv4Match prepareIPv4Match(String source, String destination) { - Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder(); + private static Ipv4Match prepareIPv4Match(final String source, final String destination) { + final Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder(); if (source != null) { ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(source)); } @@ -118,11 +118,11 @@ public class StatisticsUpdateCommiterTest { return ipv4MatchBuilder.build(); } /** - * Test method for {@link org.opendaylight.controller.md.statistics.manager.FlowComparator#ethernetMatchEquals(EthernetMatch, EthernetMatch) + * Test method for {@link org.opendaylight.controller.md.statistics.manager.impl.helper.FlowComparator#ethernetMatchEquals(EthernetMatch, EthernetMatch) */ @Test public void testEthernetMatchEquals() { - String[][][] ethernetMatchSeeds = new String[][][] { + final String[][][] ethernetMatchSeeds = new String[][][] { {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}}, {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:bc:cd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}}, {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"AA:BB:CC:DD:EE:FF", "ff:ff:ff:ff:ff:ff","0800"}}, @@ -143,7 +143,7 @@ public class StatisticsUpdateCommiterTest { {{null, null,null}, {null, null,null}}, }; - boolean[] matches = new boolean[] { + final boolean[] matches = new boolean[] { true, false, true, @@ -176,24 +176,24 @@ public class StatisticsUpdateCommiterTest { * @param ethernetMatch1 * @param ethernetMatch2 */ - private static void checkComparisonOfEthernetMatch(String macAddress1, String macAddressMask1,String etherType1, - String macAddress2, String macAddressMask2,String etherType2, boolean expectedResult) { - EthernetMatch ethernetMatch1 = prepareEthernetMatch(macAddress1, macAddressMask1,etherType1); - EthernetMatch ethernetMatch2 = prepareEthernetMatch(macAddress2, macAddressMask2,etherType2); + private static void checkComparisonOfEthernetMatch(final String macAddress1, final String macAddressMask1,final String etherType1, + final String macAddress2, final String macAddressMask2,final String etherType2, final boolean expectedResult) { + final EthernetMatch ethernetMatch1 = prepareEthernetMatch(macAddress1, macAddressMask1,etherType1); + final EthernetMatch ethernetMatch2 = prepareEthernetMatch(macAddress2, macAddressMask2,etherType2); boolean comparisonResult; try { comparisonResult = FlowComparator.ethernetMatchEquals(ethernetMatch1, ethernetMatch2); Assert.assertEquals("failed to compare: "+ethernetMatch1+" vs. "+ethernetMatch2, expectedResult, comparisonResult); - } catch (Exception e) { + } catch (final Exception e) { LOG.error("failed to compare: {} vs. {}", ethernetMatch1, ethernetMatch2, e); Assert.fail(e.getMessage()); } } - private static EthernetMatch prepareEthernetMatch(String macAddress, String macAddressMask, String etherType) { - EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder(); - EthernetSourceBuilder ethernetSourceBuilder = new EthernetSourceBuilder(); + private static EthernetMatch prepareEthernetMatch(final String macAddress, final String macAddressMask, final String etherType) { + final EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder(); + final EthernetSourceBuilder ethernetSourceBuilder = new EthernetSourceBuilder(); if (macAddress != null) { ethernetSourceBuilder.setAddress(new MacAddress(macAddress)); } @@ -201,7 +201,7 @@ public class StatisticsUpdateCommiterTest { ethernetSourceBuilder.setMask(new MacAddress(macAddressMask)); } if(etherType != null){ - EthernetTypeBuilder ethernetType = new EthernetTypeBuilder(); + final EthernetTypeBuilder ethernetType = new EthernetTypeBuilder(); ethernetType.setType(new EtherType(Long.parseLong(etherType,16))); ethernetMatchBuilder.setEthernetType(ethernetType.build()); } diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java new file mode 100644 index 0000000000..7fc171c49b --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java @@ -0,0 +1,159 @@ +package test.mock; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import test.mock.util.StatisticsManagerTest; + +import com.google.common.base.Optional; + +public class FlowStatisticsTest extends StatisticsManagerTest { + private final Object waitObject = new Object(); + +// @Test(timeout = 5000) + public void addedFlowOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Flow flow = getFlow(); + + final InstanceIdentifier flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId())) + .child(Flow.class, flow.getKey()); + final InstanceIdentifier
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId())); + final Table table = new TableBuilder().setKey(new TableKey(flow.getTableId())).setFlow(Collections.emptyList()).build(); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table); + writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow); + writeTx.put(LogicalDatastoreType.OPERATIONAL, tableII, table); + writeTx.put(LogicalDatastoreType.OPERATIONAL, flowII, flow); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + flowII.augmentation(FlowStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional flowStatDataOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, flowII.augmentation(FlowStatisticsData.class)) + .checkedGet(); + assertTrue(flowStatDataOptional.isPresent()); + assertEquals(COUNTER_64_TEST_VALUE, flowStatDataOptional.get().getFlowStatistics().getByteCount()); + + } + +// @Test(timeout = 5000) + public void deletedFlowStatsRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Flow flow = getFlow(); + + final InstanceIdentifier flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId())) + .child(Flow.class, flow.getKey()); + final InstanceIdentifier
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId())); + final Table table = new TableBuilder().setKey(new TableKey(flow.getTableId())).setFlow(Collections.emptyList()).build(); + + WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table); + writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow); + writeTx.put(LogicalDatastoreType.OPERATIONAL, tableII, table); + writeTx.put(LogicalDatastoreType.OPERATIONAL, flowII, flow); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + flowII.augmentation(FlowStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + assertCommit(writeTx.submit()); + + synchronized (waitObject) { + waitObject.wait(); + } + + ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + Optional flowStatDataOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, flowII).checkedGet(); + assertTrue(flowStatDataOptional.isPresent()); +// assertEquals(COUNTER_64_TEST_VALUE, flowStatDataOptional.get().getFlowStatistics().getByteCount()); + + writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.delete(LogicalDatastoreType.CONFIGURATION, flowII); + assertCommit(writeTx.submit()); + + readTx = getDataBroker().newReadOnlyTransaction(); + flowStatDataOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, flowII).checkedGet(); + assertFalse(flowStatDataOptional.isPresent()); + } + +// @Test(timeout = 23000) + public void getAllStatsWhenNodeIsConnectedTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityFlowStats.class); + + final Flow flow = getFlow(); + + final InstanceIdentifier
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId())); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + tableII.child(Flow.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional
tableOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).augmentation(FlowCapableNode.class) + .child(Table.class, new TableKey(flow.getTableId()))).checkedGet(); + assertTrue(tableOptional.isPresent()); + final FlowStatisticsData flowStats = tableOptional.get().getFlow().get(0).getAugmentation(FlowStatisticsData.class); + assertTrue(flowStats != null); + assertEquals(COUNTER_64_TEST_VALUE, flowStats.getFlowStatistics().getByteCount()); + } + + public class ChangeListener implements DataChangeListener { + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> change) { + synchronized (waitObject) { + waitObject.notify(); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java new file mode 100644 index 0000000000..7a61bf280f --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java @@ -0,0 +1,151 @@ +package test.mock; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityGroupStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import test.mock.util.StatisticsManagerTest; + +import com.google.common.base.Optional; + +public class GroupStatisticsTest extends StatisticsManagerTest { + private final Object waitObject = new Object(); + +// @Test(timeout = 5000) + public void addedGroupOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Group group = getGroup(); + + final InstanceIdentifier groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Group.class, group.getKey()); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group); + writeTx.put(LogicalDatastoreType.OPERATIONAL, groupII, group); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional groupOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, groupII.augmentation(NodeGroupStatistics.class)).checkedGet(); + assertTrue(groupOptional.isPresent()); + assertEquals(COUNTER_64_TEST_VALUE, groupOptional.get().getGroupStatistics().getByteCount()); + } + +// @Test(timeout = 5000) + public void deletedGroupStasRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Group group = getGroup(); + final InstanceIdentifier groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Group.class, group.getKey()); + + WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group); + writeTx.put(LogicalDatastoreType.OPERATIONAL, groupII, group); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + Optional groupOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, + groupII.augmentation(NodeGroupStatistics.class)).checkedGet(); + assertTrue(groupOptional.isPresent()); + assertEquals(COUNTER_64_TEST_VALUE, groupOptional.get().getGroupStatistics().getByteCount()); + + writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.delete(LogicalDatastoreType.CONFIGURATION, groupII); + assertCommit(writeTx.submit()); + + readTx = getDataBroker().newReadOnlyTransaction(); + groupOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, + groupII.augmentation(NodeGroupStatistics.class)).checkedGet(); + assertFalse(groupOptional.isPresent()); + + } + +// @Test(timeout = 23000) + public void getAllStatsFromConnectedNodeTest() throws ExecutionException, InterruptedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityGroupStats.class); + + final InstanceIdentifier groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Group.class, getGroup().getKey()); + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional optionalGroup = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).augmentation(FlowCapableNode.class) + .child(Group.class, getGroup().getKey())).get(); + + assertTrue(optionalGroup.isPresent()); + assertTrue(optionalGroup.get().getAugmentation(NodeGroupDescStats.class) != null); + final NodeGroupStatistics groupStats = optionalGroup.get().getAugmentation(NodeGroupStatistics.class); + assertTrue(groupStats != null); + assertEquals(COUNTER_64_TEST_VALUE, groupStats.getGroupStatistics().getByteCount()); + + readTx = getDataBroker().newReadOnlyTransaction(); + final Optional optionalGroupFeatures = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).augmentation(NodeGroupFeatures.class).child(GroupFeatures.class)).get(); + assertTrue(optionalGroupFeatures.isPresent()); + assertEquals(1, optionalGroupFeatures.get().getMaxGroups().size()); + assertEquals(MAX_GROUPS_TEST_VALUE, optionalGroupFeatures.get().getMaxGroups().get(0)); + } + + private class ChangeListener implements DataChangeListener { + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> change) { + synchronized (waitObject) { + waitObject.notify(); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java new file mode 100644 index 0000000000..a0f360c475 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java @@ -0,0 +1,150 @@ +package test.mock; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeatures; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import test.mock.util.StatisticsManagerTest; + +import com.google.common.base.Optional; + +public class MeterStatisticsTest extends StatisticsManagerTest { + private final Object waitObject = new Object(); + +// @Test(timeout = 5000) + public void addedMeterOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Meter meter = getMeter(); + final InstanceIdentifier meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Meter.class, meter.getKey()); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter); + writeTx.put(LogicalDatastoreType.OPERATIONAL, meterII, meter); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional meterStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, + meterII.augmentation(NodeMeterStatistics.class)).checkedGet(); + assertTrue(meterStatsOptional.isPresent()); + assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getByteInCount()); + assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getPacketInCount()); + } + +// @Test(timeout = 5000) + public void deletedMeterStatsRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Meter meter = getMeter(); + final InstanceIdentifier meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Meter.class, meter.getKey()); + + WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter); + writeTx.put(LogicalDatastoreType.OPERATIONAL, meterII, meter); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional meterStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, + meterII.augmentation(NodeMeterStatistics.class)).checkedGet(); + assertTrue(meterStatsOptional.isPresent()); + assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getByteInCount()); + assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getPacketInCount()); + + writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.delete(LogicalDatastoreType.CONFIGURATION, meterII); + assertCommit(writeTx.submit()); + + readTx = getDataBroker().newReadOnlyTransaction(); + final Optional meterOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, meterII).checkedGet(); + assertFalse(meterOptional.isPresent()); + } + +// @Test(timeout = 23000) + public void getAllStatsFromConnectedNodeTest() throws ExecutionException, InterruptedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNodeWithFeatures(s1Key, true); + + final InstanceIdentifier meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Meter.class, getMeter().getKey()); + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional optionalMeter = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).augmentation(FlowCapableNode.class) + .child(Meter.class, getMeter().getKey())).get(); + + assertTrue(optionalMeter.isPresent()); + assertTrue(optionalMeter.get().getAugmentation(NodeMeterConfigStats.class) != null); + final NodeMeterStatistics meterStats = optionalMeter.get().getAugmentation(NodeMeterStatistics.class); + assertTrue(meterStats != null); + assertEquals(COUNTER_64_TEST_VALUE, meterStats.getMeterStatistics().getByteInCount()); + assertEquals(COUNTER_64_TEST_VALUE, meterStats.getMeterStatistics().getPacketInCount()); + + readTx = getDataBroker().newReadOnlyTransaction(); + final Optional optionalMeterFeautures = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).augmentation(NodeMeterFeatures.class).child(MeterFeatures.class)).get(); + assertTrue(optionalMeterFeautures.isPresent()); + assertEquals(COUNTER_32_TEST_VALUE, optionalMeterFeautures.get().getMaxMeter()); + } + + private class ChangeListener implements DataChangeListener { + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> change) { + synchronized (waitObject) { + waitObject.notify(); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java new file mode 100644 index 0000000000..18bd2d42ef --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java @@ -0,0 +1,48 @@ +package test.mock; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator; +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerProvider; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import test.mock.util.StatisticsManagerTest; + +public class NodeRegistrationTest extends StatisticsManagerTest { + +// @Test + public void nodeRegistrationTest() throws ExecutionException, InterruptedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + final StatisticsManagerProvider statisticsManagerProvider = new StatisticsManagerProvider(activator); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + Thread.sleep(1000); + final InstanceIdentifier nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key); + + assertTrue(statisticsManagerProvider.getStatisticsManager().isProvidedFlowNodeActive(nodeII)); + } + +// @Test + public void nodeUnregistrationTest() throws ExecutionException, InterruptedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + final StatisticsManagerProvider statisticsManagerProvider = new StatisticsManagerProvider(activator); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + Thread.sleep(1000); + final InstanceIdentifier nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key); + + assertTrue(statisticsManagerProvider.getStatisticsManager().isProvidedFlowNodeActive(nodeII)); + + removeNode(s1Key); + Thread.sleep(1000); + assertFalse(statisticsManagerProvider.getStatisticsManager().isProvidedFlowNodeActive(nodeII)); + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java new file mode 100644 index 0000000000..9f193b03d7 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java @@ -0,0 +1,73 @@ +package test.mock; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import test.mock.util.StatisticsManagerTest; + +import com.google.common.base.Optional; + +public class PortStatisticsTest extends StatisticsManagerTest { + private final Object waitObject = new Object(); + +// @Test(timeout = 23000) + public void getPortStatisticsTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityPortStats.class); + + final InstanceIdentifier nodeConnectorII = InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).child(NodeConnector.class, new NodeConnectorKey(getNodeConnectorId())); + + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class), + new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional flowCapableNodeConnectorStatisticsDataOptional = + readTx.read(LogicalDatastoreType.OPERATIONAL, + nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class)).checkedGet(); + assertTrue(flowCapableNodeConnectorStatisticsDataOptional.isPresent()); + assertEquals(BIG_INTEGER_TEST_VALUE, + flowCapableNodeConnectorStatisticsDataOptional.get().getFlowCapableNodeConnectorStatistics() + .getReceiveDrops()); + assertEquals(BIG_INTEGER_TEST_VALUE, + flowCapableNodeConnectorStatisticsDataOptional.get().getFlowCapableNodeConnectorStatistics() + .getCollisionCount()); + } + + private class ChangeListener implements DataChangeListener { + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> change) { + synchronized (waitObject) { + waitObject.notify(); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java new file mode 100644 index 0000000000..bb9bd21134 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java @@ -0,0 +1,197 @@ +package test.mock; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.port.mod.port.Port; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import test.mock.util.StatisticsManagerTest; + +import com.google.common.base.Optional; + + +public class QueueStatisticsTest extends StatisticsManagerTest { + private final Object waitObject = new Object(); + +// @Test(timeout = 5000) + public void addedQueueOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Port port = getPort(); + + final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder(); + final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder(); + fcncBuilder.setConfiguration(port.getConfiguration()); + fcncBuilder.setPortNumber(port.getPortNumber()); + fcncBuilder.setQueue(Collections.emptyList()); + ncBuilder.setKey(new NodeConnectorKey(new NodeConnectorId("connector.1"))); + ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build()); + + + final Queue queue = getQueue(); + final InstanceIdentifier queueII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .child(NodeConnector.class, ncBuilder.getKey()).augmentation(FlowCapableNodeConnector.class) + .child(Queue.class, queue.getKey()); + final InstanceIdentifier nodeConnectorII = InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).child(NodeConnector.class, ncBuilder.getKey()); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, nodeConnectorII, ncBuilder.build()); + writeTx.put(LogicalDatastoreType.CONFIGURATION, queueII, queue); + writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build()); + writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, queue); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional queueStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, + queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class)).checkedGet(); + assertTrue(queueStatsOptional.isPresent()); + assertEquals(COUNTER_64_TEST_VALUE, + queueStatsOptional.get().getFlowCapableNodeConnectorQueueStatistics().getTransmittedBytes()); + } + +// @Test(timeout = 5000) + public void deletedQueueStatsRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNode(s1Key); + + final Port port = getPort(); + + final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder(); + final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder(); + fcncBuilder.setConfiguration(port.getConfiguration()); + fcncBuilder.setPortNumber(port.getPortNumber()); + fcncBuilder.setQueue(Collections.emptyList()); + ncBuilder.setKey(new NodeConnectorKey(new NodeConnectorId("connector.1"))); + ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build()); + + + final Queue queue = getQueue(); + final InstanceIdentifier queueII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .child(NodeConnector.class, ncBuilder.getKey()).augmentation(FlowCapableNodeConnector.class) + .child(Queue.class, queue.getKey()); + final InstanceIdentifier nodeConnectorII = InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key).child(NodeConnector.class, ncBuilder.getKey()); + + WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, nodeConnectorII, ncBuilder.build()); + writeTx.put(LogicalDatastoreType.CONFIGURATION, queueII, queue); + writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build()); + writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, queue); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class), + new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + Optional queueStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, + queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class)).checkedGet(); + assertTrue(queueStatsOptional.isPresent()); + assertEquals(COUNTER_64_TEST_VALUE, + queueStatsOptional.get().getFlowCapableNodeConnectorQueueStatistics().getTransmittedBytes()); + + writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.delete(LogicalDatastoreType.CONFIGURATION, queueII); + assertCommit(writeTx.submit()); + + readTx = getDataBroker().newReadOnlyTransaction(); + queueStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, + queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class)).checkedGet(); + assertFalse(queueStatsOptional.isPresent()); + } + +// @Test(timeout = 23000) + public void getAllStatsFromConnectedNodeTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityQueueStats.class); + + final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder(); + final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder(); + ncBuilder.setKey(new NodeConnectorKey(getNodeConnectorId())); + ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build()); + + final InstanceIdentifier nodeConnectorII = InstanceIdentifier.create(Nodes.class) + .child(Node.class, s1Key) + .child(NodeConnector.class, ncBuilder.getKey()); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build()); + final InstanceIdentifier queueII = nodeConnectorII.augmentation(FlowCapableNodeConnector.class) + .child(Queue.class, getQueue().getKey()); + final QueueBuilder qBuilder = new QueueBuilder(getQueue()); + writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, qBuilder.build()); + assertCommit(writeTx.submit()); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional queueOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, queueII).checkedGet(); + assertTrue(queueOptional.isPresent()); + final FlowCapableNodeConnectorQueueStatisticsData queueStats = + queueOptional.get().getAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class); + assertTrue(queueStats != null); + assertEquals(COUNTER_64_TEST_VALUE, + queueStats.getFlowCapableNodeConnectorQueueStatistics().getTransmittedBytes()); + } + + private class ChangeListener implements DataChangeListener { + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> change) { + synchronized (waitObject) { + waitObject.notify(); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java new file mode 100644 index 0000000000..f0c0fedb70 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java @@ -0,0 +1,71 @@ +package test.mock; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import test.mock.util.StatisticsManagerTest; + +import com.google.common.base.Optional; + +public class TableStatisticsTest extends StatisticsManagerTest { + private final Object waitObject = new Object(); + +// @Test(timeout = 23000) + public void getTableStatisticsTest() throws ExecutionException, InterruptedException, ReadFailedException { + final StatisticsManagerActivator activator = new StatisticsManagerActivator(); + activator.onSessionInitiated(providerContext); + + addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityTableStats.class); + + final TableId tableId = getTableId(); + final InstanceIdentifier
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId.getValue())); + + getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + tableII.augmentation(FlowTableStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE); + + synchronized (waitObject) { + waitObject.wait(); + } + + final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction(); + final Optional flowTableStatisticsDataOptional = readTx.read( + LogicalDatastoreType.OPERATIONAL, tableII.augmentation(FlowTableStatisticsData.class)).checkedGet(); + assertTrue(flowTableStatisticsDataOptional.isPresent()); + assertEquals(COUNTER_32_TEST_VALUE, + flowTableStatisticsDataOptional.get().getFlowTableStatistics().getActiveFlows()); + assertEquals(COUNTER_64_TEST_VALUE, + flowTableStatisticsDataOptional.get().getFlowTableStatistics().getPacketsLookedUp()); + } + + private class ChangeListener implements DataChangeListener { + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> change) { + synchronized (waitObject) { + waitObject.notify(); + } + } + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java new file mode 100644 index 0000000000..f9efa51d41 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java @@ -0,0 +1,60 @@ +/* + * 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 test.mock.util; + +import com.google.common.util.concurrent.ListenableFuture; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class AbstractDataBrokerTest extends AbstractSchemaAwareTest { + + private DataBrokerTestCustomizer testCustomizer; + private DataBroker dataBroker; + private DOMDataBroker domBroker; + + + @Override + protected void setupWithSchema(final SchemaContext context) { + testCustomizer = createDataBrokerTestCustomizer(); + dataBroker = testCustomizer.createDataBroker(); + domBroker = testCustomizer.createDOMDataBroker(); + testCustomizer.updateSchema(context); + setupWithDataBroker(dataBroker); + } + + protected void setupWithDataBroker(final DataBroker dataBroker) { + // Intentionally left No-op, subclasses may customize it + } + + protected DataBrokerTestCustomizer createDataBrokerTestCustomizer() { + return new DataBrokerTestCustomizer(); + } + + public DataBroker getDataBroker() { + return dataBroker; + } + + public DOMDataBroker getDomBroker() { + return domBroker; + } + + protected static final void assertCommit(final ListenableFuture commit) { + try { + commit.get(500, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + throw new IllegalStateException(e); + } + } + + +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java new file mode 100644 index 0000000000..d520d59cdd --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java @@ -0,0 +1,44 @@ +/* + * 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 test.mock.util; + +import org.junit.Before; +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext; +import org.opendaylight.yangtools.yang.binding.YangModuleInfo; +import org.opendaylight.yangtools.yang.binding.util.BindingReflections; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +public abstract class AbstractSchemaAwareTest { + + private Iterable moduleInfos; + private SchemaContext schemaContext; + + + protected Iterable getModuleInfos() { + return BindingReflections.loadModuleInfos(); + } + + + @Before + public final void setup() { + moduleInfos = getModuleInfos(); + ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create(); + moduleContext.addModuleInfos(moduleInfos); + schemaContext = moduleContext.tryToCreateSchemaContext().get(); + setupWithSchema(schemaContext); + } + + /** + * Setups test with Schema context. + * This method is called before {@link #setupWithSchemaService(SchemaService)} + * + * @param context + */ + protected abstract void setupWithSchema(SchemaContext context); + +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/BundleContextMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/BundleContextMock.java new file mode 100644 index 0000000000..37cea44ab0 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/BundleContextMock.java @@ -0,0 +1,149 @@ +package test.mock.util; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.BundleListener; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Dictionary; + +public class BundleContextMock implements BundleContext { + @Override + public String getProperty(String s) { + return null; + } + + @Override + public Bundle getBundle() { + return null; + } + + @Override + public Bundle installBundle(String s, InputStream inputStream) throws BundleException { + return null; + } + + @Override + public Bundle installBundle(String s) throws BundleException { + return null; + } + + @Override + public Bundle getBundle(long l) { + return null; + } + + @Override + public Bundle[] getBundles() { + return new Bundle[0]; + } + + @Override + public void addServiceListener(ServiceListener serviceListener, String s) throws InvalidSyntaxException { + + } + + @Override + public void addServiceListener(ServiceListener serviceListener) { + + } + + @Override + public void removeServiceListener(ServiceListener serviceListener) { + + } + + @Override + public void addBundleListener(BundleListener bundleListener) { + + } + + @Override + public void removeBundleListener(BundleListener bundleListener) { + + } + + @Override + public void addFrameworkListener(FrameworkListener frameworkListener) { + + } + + @Override + public void removeFrameworkListener(FrameworkListener frameworkListener) { + + } + + @Override + public ServiceRegistration registerService(String[] strings, Object o, Dictionary stringDictionary) { + return null; + } + + @Override + public ServiceRegistration registerService(String s, Object o, Dictionary stringDictionary) { + return null; + } + + @Override + public ServiceRegistration registerService(Class sClass, S s, Dictionary stringDictionary) { + return null; + } + + @Override + public ServiceReference[] getServiceReferences(String s, String s2) throws InvalidSyntaxException { + return new ServiceReference[0]; + } + + @Override + public ServiceReference[] getAllServiceReferences(String s, String s2) throws InvalidSyntaxException { + return new ServiceReference[0]; + } + + @Override + public ServiceReference getServiceReference(String s) { + return null; + } + + @Override + public ServiceReference getServiceReference(Class sClass) { + return null; + } + + @Override + public Collection> getServiceReferences(Class sClass, String s) throws InvalidSyntaxException { + return null; + } + + @Override + public S getService(ServiceReference sServiceReference) { + return null; + } + + @Override + public boolean ungetService(ServiceReference serviceReference) { + return false; + } + + @Override + public File getDataFile(String s) { + return null; + } + + @Override + public Filter createFilter(String s) throws InvalidSyntaxException { + return null; + } + + @Override + public Bundle getBundle(String s) { + return null; + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java new file mode 100644 index 0000000000..36ab41fa68 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java @@ -0,0 +1,111 @@ +/* + * 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 test.mock.util; + +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import javassist.ClassPool; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec; +import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker; +import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl; +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.controller.sal.core.spi.data.DOMStore; +import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator; +import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator; +import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy; +import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl; +import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +public class DataBrokerTestCustomizer { + + private DOMDataBroker domDataBroker; + private final RuntimeGeneratedMappingServiceImpl mappingService; + private final MockSchemaService schemaService; + private ImmutableMap datastores; + private final BindingToNormalizedNodeCodec bindingToNormalized ; + + public ImmutableMap createDatastores() { + return ImmutableMap.builder() + .put(LogicalDatastoreType.OPERATIONAL, createOperationalDatastore()) + .put(LogicalDatastoreType.CONFIGURATION,createConfigurationDatastore()) + .build(); + } + + public DataBrokerTestCustomizer() { + schemaService = new MockSchemaService(); + ClassPool pool = ClassPool.getDefault(); + mappingService = new RuntimeGeneratedMappingServiceImpl(pool); + DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(pool)); + BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator); + GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(); + bindingToNormalized = new BindingToNormalizedNodeCodec(loading, mappingService, codecRegistry); + schemaService.registerSchemaContextListener(bindingToNormalized); + } + + public DOMStore createConfigurationDatastore() { + InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG", + MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor()); + schemaService.registerSchemaContextListener(store); + return store; + } + + public DOMStore createOperationalDatastore() { + InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", + MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor()); + schemaService.registerSchemaContextListener(store); + return store; + } + + public DOMDataBroker createDOMDataBroker() { + return new DOMDataBrokerImpl(getDatastores(), getCommitCoordinatorExecutor()); + } + + public ListeningExecutorService getCommitCoordinatorExecutor() { + return MoreExecutors.sameThreadExecutor(); + } + + public DataBroker createDataBroker() { + return new ForwardedBindingDataBroker(getDOMDataBroker(), bindingToNormalized, schemaService ); + } + + public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() { + return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), bindingToNormalized, getSchemaService(), MoreExecutors.sameThreadExecutor()); + } + + private SchemaService getSchemaService() { + return schemaService; + } + + private DOMDataBroker getDOMDataBroker() { + if(domDataBroker == null) { + domDataBroker = createDOMDataBroker(); + } + return domDataBroker; + } + + private synchronized ImmutableMap getDatastores() { + if (datastores == null) { + datastores = createDatastores(); + } + return datastores; + } + + public void updateSchema(final SchemaContext ctx) { + schemaService.changeSchema(ctx); + mappingService.onGlobalContextUpdated(ctx); + } + +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/FlowMockGenerator.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/FlowMockGenerator.java new file mode 100644 index 0000000000..fb5351b43a --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/FlowMockGenerator.java @@ -0,0 +1,30 @@ +package test.mock.util; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie; + +import java.math.BigInteger; +import java.util.Random; + +public class FlowMockGenerator { + private static final Random rnd = new Random(); + private static final FlowBuilder flowBuilder = new FlowBuilder(); + + public static Flow getRandomFlow() { + flowBuilder.setKey(new FlowKey(new FlowId("flow." + rnd.nextInt(1000)))); + flowBuilder.setOutGroup(TestUtils.nextLong(0, 4294967296L)); + flowBuilder.setTableId((short) rnd.nextInt(256)); + flowBuilder.setOutPort(BigInteger.valueOf(TestUtils.nextLong(0, Long.MAX_VALUE))); + flowBuilder.setStrict(rnd.nextBoolean()); + flowBuilder.setContainerName("container." + rnd.nextInt(1000)); + flowBuilder.setBarrier(rnd.nextBoolean()); + flowBuilder.setMatch(MatchMockGenerator.getRandomMatch()); + flowBuilder.setPriority(rnd.nextInt(65535)); + flowBuilder.setCookie(new FlowCookie(BigInteger.valueOf(TestUtils.nextLong(0, Long.MAX_VALUE)))); + flowBuilder.setCookieMask(flowBuilder.getCookie()); + return flowBuilder.build(); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/GroupMockGenerator.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/GroupMockGenerator.java new file mode 100644 index 0000000000..183524d4c0 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/GroupMockGenerator.java @@ -0,0 +1,23 @@ +package test.mock.util; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; + +import java.util.Random; + +public class GroupMockGenerator { + private static final Random rnd = new Random(); + private static final GroupBuilder groupBuilder = new GroupBuilder(); + + public static Group getRandomGroup() { + groupBuilder.setKey(new GroupKey(new GroupId(TestUtils.nextLong(0, 4294967295L)))); + groupBuilder.setContainerName("container." + rnd.nextInt(1000)); + groupBuilder.setBarrier(rnd.nextBoolean()); + groupBuilder.setGroupName("group." + rnd.nextInt(1000)); + groupBuilder.setGroupType(GroupTypes.forValue(rnd.nextInt(4))); + return groupBuilder.build(); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MatchMockGenerator.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MatchMockGenerator.java new file mode 100644 index 0000000000..8b603c26a5 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MatchMockGenerator.java @@ -0,0 +1,30 @@ +package test.mock.util; + +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.MetadataBuilder; + +import java.math.BigInteger; +import java.util.Random; + +public class MatchMockGenerator { + private static final Random rnd = new Random(); + private static final MatchBuilder matchBuilder = new MatchBuilder(); + private static final IpMatchBuilder ipMatchBuilder = new IpMatchBuilder(); + private static final MetadataBuilder metadataBuilder = new MetadataBuilder(); + + public static Match getRandomMatch() { + matchBuilder.setInPort(new NodeConnectorId("port." + rnd.nextInt(500))); + ipMatchBuilder.setIpDscp(new Dscp((short) rnd.nextInt(64))).build(); + ipMatchBuilder.setIpEcn((short) rnd.nextInt(256)); + ipMatchBuilder.setIpProtocol((short) rnd.nextInt(256)); + matchBuilder.setIpMatch(ipMatchBuilder.build()); + metadataBuilder.setMetadata(BigInteger.valueOf(TestUtils.nextLong(0, Long.MAX_VALUE))); + metadataBuilder.setMetadataMask(BigInteger.valueOf(TestUtils.nextLong(0, Long.MAX_VALUE))); + matchBuilder.setMetadata(metadataBuilder.build()); + return matchBuilder.build(); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MeterMockGenerator.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MeterMockGenerator.java new file mode 100644 index 0000000000..63ebcb0ea2 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MeterMockGenerator.java @@ -0,0 +1,35 @@ +package test.mock.util; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.BandId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeadersBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderKey; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class MeterMockGenerator { + private static final Random rnd = new Random(); + private static final MeterBuilder meterBuilder = new MeterBuilder(); + private static final MeterBandHeaderBuilder meterBandHeaderBuilder = new MeterBandHeaderBuilder(); + private static final MeterBandHeadersBuilder meterBandHeadersBuilder = new MeterBandHeadersBuilder(); + + public static Meter getRandomMeter() { + meterBandHeaderBuilder.setKey(new MeterBandHeaderKey(new BandId(TestUtils.nextLong(0, 4294967295L)))); + meterBandHeaderBuilder.setBandBurstSize(TestUtils.nextLong(0, 4294967295L)); + meterBandHeaderBuilder.setBandRate(TestUtils.nextLong(0, 4294967295L)); + List meterBandHeaders = new ArrayList<>(); + meterBuilder.setKey(new MeterKey(new MeterId(TestUtils.nextLong(0, 4294967295L)))); + meterBuilder.setBarrier(rnd.nextBoolean()); + meterBuilder.setContainerName("container." + rnd.nextInt(1000)); + meterBuilder.setMeterName("meter." + rnd.nextInt(1000)); + meterBuilder.setMeterBandHeaders(meterBandHeadersBuilder.setMeterBandHeader(meterBandHeaders).build()); + return meterBuilder.build(); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MockSchemaService.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MockSchemaService.java new file mode 100644 index 0000000000..b4876a3ee0 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/MockSchemaService.java @@ -0,0 +1,62 @@ +/* + * 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 test.mock.util; + +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.util.ListenerRegistry; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; + +@SuppressWarnings("deprecation") +public final class MockSchemaService implements SchemaService, SchemaContextProvider { + + private SchemaContext schemaContext; + + ListenerRegistry listeners = ListenerRegistry.create(); + + @Override + public void addModule(final Module module) { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized SchemaContext getGlobalContext() { + return schemaContext; + } + + @Override + public synchronized SchemaContext getSessionContext() { + return schemaContext; + } + + @Override + public ListenerRegistration registerSchemaContextListener( + final SchemaContextListener listener) { + return listeners.register(listener); + } + + @Override + public void removeModule(final Module module) { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized SchemaContext getSchemaContext() { + return schemaContext; + } + + public synchronized void changeSchema(final SchemaContext newContext) { + schemaContext = newContext; + for (ListenerRegistration listener : listeners) { + listener.getInstance().onGlobalContextUpdated(schemaContext); + } + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/NotificationProviderServiceHelper.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/NotificationProviderServiceHelper.java new file mode 100644 index 0000000000..2d85f62ab5 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/NotificationProviderServiceHelper.java @@ -0,0 +1,29 @@ +package test.mock.util; + +import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder; +import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl; +import org.opendaylight.yangtools.yang.binding.Notification; + +import java.util.Timer; +import java.util.TimerTask; + +public class NotificationProviderServiceHelper { + private NotificationBrokerImpl notifBroker = new NotificationBrokerImpl(SingletonHolder.getDefaultNotificationExecutor()); + + public NotificationBrokerImpl getNotifBroker() { + return notifBroker; + } + + public void pushDelayedNotification(final Notification notification, int delay) { + new Timer().schedule(new TimerTask() { + @Override + public void run() { + notifBroker.publish(notification); + } + }, delay); + } + + public void pushNotification(final Notification notification) { + notifBroker.publish(notification); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java new file mode 100644 index 0000000000..2628bb9f41 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java @@ -0,0 +1,116 @@ +package test.mock.util; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicLong; + +public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowStatisticsService { + NotificationProviderServiceHelper notifService; + AtomicLong transNum = new AtomicLong(); + + public OpendaylightFlowStatisticsServiceMock(NotificationProviderServiceHelper notifService) { + this.notifService = notifService; + } + + @Override + public Future> getAggregateFlowStatisticsFromFlowTableForAllFlows(GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput input) { + GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutputBuilder builder = new GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getAggregateFlowStatisticsFromFlowTableForGivenMatch(GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) { + GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder builder = new GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + AggregateFlowStatisticsUpdateBuilder afsuBuilder = new AggregateFlowStatisticsUpdateBuilder(); + afsuBuilder.setMoreReplies(false); + afsuBuilder.setTransactionId(transId); + afsuBuilder.setByteCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + afsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + notifService.pushDelayedNotification(afsuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getAllFlowStatisticsFromFlowTable(GetAllFlowStatisticsFromFlowTableInput input) { + GetAllFlowStatisticsFromFlowTableOutputBuilder builder = new GetAllFlowStatisticsFromFlowTableOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getAllFlowsStatisticsFromAllFlowTables(GetAllFlowsStatisticsFromAllFlowTablesInput input) { + GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder builder = new GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + List flowAndStatisticsMapLists = new ArrayList<>(); + FlowsStatisticsUpdateBuilder flowsStatisticsUpdateBuilder = new FlowsStatisticsUpdateBuilder(); + flowsStatisticsUpdateBuilder.setTransactionId(transId); + flowsStatisticsUpdateBuilder.setMoreReplies(false); + flowsStatisticsUpdateBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + FlowAndStatisticsMapListBuilder flowAndStatisticsMapListBuilder = new FlowAndStatisticsMapListBuilder(StatisticsManagerTest.getFlow()); + flowAndStatisticsMapListBuilder.setTableId(StatisticsManagerTest.getFlow().getTableId()); + flowAndStatisticsMapListBuilder.setContainerName(StatisticsManagerTest.getFlow().getContainerName()); + flowAndStatisticsMapListBuilder.setBarrier(StatisticsManagerTest.getFlow().isBarrier()); + flowAndStatisticsMapListBuilder.setByteCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + flowAndStatisticsMapLists.add(flowAndStatisticsMapListBuilder.build()); + flowsStatisticsUpdateBuilder.setFlowAndStatisticsMapList(flowAndStatisticsMapLists); + notifService.pushDelayedNotification(flowsStatisticsUpdateBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getFlowStatisticsFromFlowTable(GetFlowStatisticsFromFlowTableInput input) { + GetFlowStatisticsFromFlowTableOutputBuilder builder = new GetFlowStatisticsFromFlowTableOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + List flowAndStatisticsMapLists = new ArrayList<>(); + FlowsStatisticsUpdateBuilder flowsStatisticsUpdateBuilder = new FlowsStatisticsUpdateBuilder(); + flowsStatisticsUpdateBuilder.setTransactionId(transId); + flowsStatisticsUpdateBuilder.setMoreReplies(false); + flowsStatisticsUpdateBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + FlowAndStatisticsMapListBuilder flowAndStatisticsMapListBuilder = new FlowAndStatisticsMapListBuilder(input); + flowAndStatisticsMapListBuilder.setTableId(input.getTableId()); + flowAndStatisticsMapListBuilder.setContainerName(input.getContainerName()); + flowAndStatisticsMapListBuilder.setBarrier(input.isBarrier()); + flowAndStatisticsMapListBuilder.setByteCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + flowAndStatisticsMapLists.add(flowAndStatisticsMapListBuilder.build()); + flowsStatisticsUpdateBuilder.setFlowAndStatisticsMapList(flowAndStatisticsMapLists); + notifService.pushDelayedNotification(flowsStatisticsUpdateBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java new file mode 100644 index 0000000000..42be70892c --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java @@ -0,0 +1,57 @@ +package test.mock.util; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicLong; + +public class OpendaylightFlowTableStatisticsServiceMock implements OpendaylightFlowTableStatisticsService { + NotificationProviderServiceHelper notifService; + AtomicLong transNum = new AtomicLong(); + + public OpendaylightFlowTableStatisticsServiceMock(NotificationProviderServiceHelper notifService) { + this.notifService = notifService; + } + + @Override + public Future> getFlowTablesStatistics(GetFlowTablesStatisticsInput input) { + GetFlowTablesStatisticsOutputBuilder builder = new GetFlowTablesStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + FlowTableStatisticsUpdateBuilder ftsBuilder = new FlowTableStatisticsUpdateBuilder(); + FlowTableAndStatisticsMapBuilder ftasmBuilder = new FlowTableAndStatisticsMapBuilder(); + List tableAndStatisticsMaps = new ArrayList<>(); + ftasmBuilder.setKey(new FlowTableAndStatisticsMapKey(StatisticsManagerTest.getTableId())); + ftasmBuilder.setActiveFlows(StatisticsManagerTest.COUNTER_32_TEST_VALUE); + tableAndStatisticsMaps.add(ftasmBuilder.build()); + ftsBuilder.setTransactionId(transId); + ftsBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + ftsBuilder.setFlowTableAndStatisticsMap(tableAndStatisticsMaps); + ftsBuilder.setMoreReplies(true); + notifService.pushDelayedNotification(ftsBuilder.build(), 0); // 1st notification + ftsBuilder.setMoreReplies(false); + ftasmBuilder.setPacketsLookedUp(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + tableAndStatisticsMaps.clear(); + tableAndStatisticsMaps.add(ftasmBuilder.build()); + ftsBuilder.setFlowTableAndStatisticsMap(tableAndStatisticsMaps); + notifService.pushDelayedNotification(ftsBuilder.build(), 0); // 2nd notification + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java new file mode 100644 index 0000000000..7e7342f609 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java @@ -0,0 +1,123 @@ +package test.mock.util; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStatsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStatsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStatsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStatsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicLong; + +public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroupStatisticsService { + NotificationProviderServiceHelper notifService; + AtomicLong transNum = new AtomicLong(); + + public OpendaylightGroupStatisticsServiceMock(NotificationProviderServiceHelper notifService) { + this.notifService = notifService; + } + + @Override + public Future> getAllGroupStatistics(GetAllGroupStatisticsInput input) { + GetAllGroupStatisticsOutputBuilder builder = new GetAllGroupStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + List groupStats = new ArrayList<>(); + GroupStatsBuilder gsBuilder = new GroupStatsBuilder(); + GroupStatisticsUpdatedBuilder gsuBuilder = new GroupStatisticsUpdatedBuilder(); + gsBuilder.setKey(new GroupStatsKey(StatisticsManagerTest.getGroup().getGroupId())); + gsBuilder.setByteCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + groupStats.add(gsBuilder.build()); + builder.setGroupStats(groupStats); + gsuBuilder.setTransactionId(transId); + gsuBuilder.setMoreReplies(false); + gsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + gsuBuilder.setGroupStats(groupStats); + notifService.pushDelayedNotification(gsuBuilder.build(), 500); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getGroupDescription(GetGroupDescriptionInput input) { + GetGroupDescriptionOutputBuilder builder = new GetGroupDescriptionOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + List groupDescStats = new ArrayList<>(); + GroupDescStatsUpdatedBuilder gdsuBuilder = new GroupDescStatsUpdatedBuilder(); + GroupDescStatsBuilder gdsBuilder = new GroupDescStatsBuilder(); + gdsBuilder.setKey(new GroupDescStatsKey(StatisticsManagerTest.getGroup().getGroupId())); + gdsBuilder.setBuckets(StatisticsManagerTest.getGroup().getBuckets()); + gdsBuilder.setContainerName(StatisticsManagerTest.getGroup().getContainerName()); + gdsBuilder.setGroupName(StatisticsManagerTest.getGroup().getGroupName()); + gdsBuilder.setGroupType(StatisticsManagerTest.getGroup().getGroupType()); + groupDescStats.add(gdsBuilder.build()); + builder.setGroupDescStats(groupDescStats); + gdsuBuilder.setTransactionId(transId); + gdsuBuilder.setMoreReplies(false); + gdsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + gdsuBuilder.setGroupDescStats(groupDescStats); + notifService.pushDelayedNotification(gdsuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getGroupFeatures(GetGroupFeaturesInput input) { + GetGroupFeaturesOutputBuilder builder = new GetGroupFeaturesOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + GroupFeaturesUpdatedBuilder gfuBuilder = new GroupFeaturesUpdatedBuilder(); + gfuBuilder.setTransactionId(transId); + gfuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + gfuBuilder.setMoreReplies(false); + List maxGroups = new ArrayList<>(); + maxGroups.add(StatisticsManagerTest.MAX_GROUPS_TEST_VALUE); + gfuBuilder.setMaxGroups(maxGroups); + notifService.pushDelayedNotification(gfuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getGroupStatistics(GetGroupStatisticsInput input) { + GetGroupStatisticsOutputBuilder builder = new GetGroupStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + GroupStatsBuilder gsBuilder = new GroupStatsBuilder(); + List groupStats = new ArrayList<>(); + gsBuilder.setKey(new GroupStatsKey(input.getGroupId())); + gsBuilder.setByteCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + groupStats.add(gsBuilder.build()); + GroupStatisticsUpdatedBuilder gsuBuilder = new GroupStatisticsUpdatedBuilder(); + gsuBuilder.setTransactionId(transId); + gsuBuilder.setMoreReplies(false); + gsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + gsuBuilder.setGroupStats(groupStats); + notifService.pushDelayedNotification(gsuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java new file mode 100644 index 0000000000..2d65d1ebed --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java @@ -0,0 +1,119 @@ +package test.mock.util; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStatsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsKey; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicLong; + +public class OpendaylightMeterStatisticsServiceMock implements OpendaylightMeterStatisticsService { + NotificationProviderServiceHelper notifService; + AtomicLong transNum = new AtomicLong(); + + public OpendaylightMeterStatisticsServiceMock(NotificationProviderServiceHelper notifService) { + this.notifService = notifService; + } + + @Override + public Future> getAllMeterConfigStatistics(GetAllMeterConfigStatisticsInput input) { + GetAllMeterConfigStatisticsOutputBuilder builder = new GetAllMeterConfigStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + List meterConfigStats = new ArrayList<>(); + MeterConfigStatsBuilder mcsBuilder = new MeterConfigStatsBuilder(); + mcsBuilder.setMeterId(StatisticsManagerTest.getMeter().getMeterId()); + mcsBuilder.setMeterName(StatisticsManagerTest.getMeter().getMeterName()); + mcsBuilder.setContainerName(StatisticsManagerTest.getMeter().getContainerName()); + meterConfigStats.add(mcsBuilder.build()); + builder.setMeterConfigStats(meterConfigStats); + MeterConfigStatsUpdatedBuilder mscuBuilder = new MeterConfigStatsUpdatedBuilder(); + mscuBuilder.setTransactionId(transId); + mscuBuilder.setMoreReplies(false); + mscuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + mscuBuilder.setMeterConfigStats(meterConfigStats); + notifService.pushDelayedNotification(mscuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getAllMeterStatistics(GetAllMeterStatisticsInput input) { + GetAllMeterStatisticsOutputBuilder builder = new GetAllMeterStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + MeterStatsBuilder msBuilder = new MeterStatsBuilder(); + msBuilder.setByteInCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + msBuilder.setPacketInCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + msBuilder.setKey(new MeterStatsKey(StatisticsManagerTest.getMeter().getMeterId())); + List meterStats = new ArrayList<>(); + meterStats.add(msBuilder.build()); + MeterStatisticsUpdatedBuilder msuBuilder = new MeterStatisticsUpdatedBuilder(); + msuBuilder.setTransactionId(transId); + msuBuilder.setMoreReplies(false); + msuBuilder.setMeterStats(meterStats); + msuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + notifService.pushDelayedNotification(msuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getMeterFeatures(GetMeterFeaturesInput input) { + GetMeterFeaturesOutputBuilder builder = new GetMeterFeaturesOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + MeterFeaturesUpdatedBuilder mfuBuilder = new MeterFeaturesUpdatedBuilder(); + mfuBuilder.setTransactionId(transId); + mfuBuilder.setMoreReplies(false); + mfuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + mfuBuilder.setMaxMeter(StatisticsManagerTest.COUNTER_32_TEST_VALUE); + notifService.pushDelayedNotification(mfuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getMeterStatistics(GetMeterStatisticsInput input) { + GetMeterStatisticsOutputBuilder builder = new GetMeterStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + MeterStatsBuilder msBuilder = new MeterStatsBuilder(); + msBuilder.setKey(new MeterStatsKey(input.getMeterId())); + msBuilder.setByteInCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + msBuilder.setPacketInCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + List meterStats = new ArrayList<>(); + meterStats.add(msBuilder.build()); + MeterStatisticsUpdatedBuilder msuBuilder = new MeterStatisticsUpdatedBuilder(); + msuBuilder.setTransactionId(transId); + msuBuilder.setMoreReplies(false); + msuBuilder.setMeterStats(meterStats); + msuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + notifService.pushDelayedNotification(msuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java new file mode 100644 index 0000000000..7164c56c1b --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java @@ -0,0 +1,67 @@ +package test.mock.util; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapKey; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicLong; + +public class OpendaylightPortStatisticsServiceMock implements OpendaylightPortStatisticsService { + NotificationProviderServiceHelper notifService; + AtomicLong transNum = new AtomicLong(); + + public OpendaylightPortStatisticsServiceMock(NotificationProviderServiceHelper notifService) { + this.notifService = notifService; + } + + @Override + public Future> getAllNodeConnectorsStatistics(GetAllNodeConnectorsStatisticsInput input) { + GetAllNodeConnectorsStatisticsOutputBuilder builder = new GetAllNodeConnectorsStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + NodeConnectorStatisticsUpdateBuilder ncsuBuilder = new NodeConnectorStatisticsUpdateBuilder(); + NodeConnectorStatisticsAndPortNumberMapBuilder ncsapnmBuilder = new NodeConnectorStatisticsAndPortNumberMapBuilder(); + List nodeConnectorStatisticsAndPortNumberMaps = new ArrayList<>(); + ncsapnmBuilder.setKey(new NodeConnectorStatisticsAndPortNumberMapKey(StatisticsManagerTest.getNodeConnectorId())); + ncsapnmBuilder.setReceiveDrops(StatisticsManagerTest.BIG_INTEGER_TEST_VALUE); + nodeConnectorStatisticsAndPortNumberMaps.add(ncsapnmBuilder.build()); + ncsuBuilder.setTransactionId(new TransactionId(BigInteger.valueOf(1))); + ncsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + ncsuBuilder.setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatisticsAndPortNumberMaps); + ncsuBuilder.setMoreReplies(true); + notifService.pushDelayedNotification(ncsuBuilder.build(), 0); // 1st notification + ncsuBuilder.setMoreReplies(false); + ncsapnmBuilder.setCollisionCount(StatisticsManagerTest.BIG_INTEGER_TEST_VALUE); + nodeConnectorStatisticsAndPortNumberMaps.clear(); + nodeConnectorStatisticsAndPortNumberMaps.add(ncsapnmBuilder.build()); + ncsuBuilder.setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatisticsAndPortNumberMaps); + notifService.pushDelayedNotification(ncsuBuilder.build(), 10); // 2nd notification + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getNodeConnectorStatistics(GetNodeConnectorStatisticsInput input) { + GetNodeConnectorStatisticsOutputBuilder builder = new GetNodeConnectorStatisticsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java new file mode 100644 index 0000000000..4f6806b8ca --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java @@ -0,0 +1,83 @@ +package test.mock.util; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromGivenPortInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromGivenPortOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromGivenPortOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPortInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPortOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPortOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapKey; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicLong; + +public class OpendaylightQueueStatisticsServiceMock implements OpendaylightQueueStatisticsService { + NotificationProviderServiceHelper notifService; + AtomicLong transNum = new AtomicLong(); + + public OpendaylightQueueStatisticsServiceMock(NotificationProviderServiceHelper notifService) { + this.notifService = notifService; + } + + @Override + public Future> getAllQueuesStatisticsFromAllPorts(GetAllQueuesStatisticsFromAllPortsInput input) { + GetAllQueuesStatisticsFromAllPortsOutputBuilder builder = new GetAllQueuesStatisticsFromAllPortsOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + QueueStatisticsUpdateBuilder qsuBuilder = new QueueStatisticsUpdateBuilder(); + QueueIdAndStatisticsMapBuilder qiasmBuilder = new QueueIdAndStatisticsMapBuilder(); + List queueIdAndStatisticsMaps = new ArrayList<>(); + qsuBuilder.setMoreReplies(false); + qsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + qsuBuilder.setTransactionId(transId); + qiasmBuilder.setTransmittedBytes(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + qiasmBuilder.setKey(new QueueIdAndStatisticsMapKey(StatisticsManagerTest.getNodeConnectorId(), StatisticsManagerTest.getQueue().getQueueId())); + queueIdAndStatisticsMaps.add(qiasmBuilder.build()); + qsuBuilder.setQueueIdAndStatisticsMap(queueIdAndStatisticsMaps); + notifService.pushDelayedNotification(qsuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getAllQueuesStatisticsFromGivenPort(GetAllQueuesStatisticsFromGivenPortInput input) { + GetAllQueuesStatisticsFromGivenPortOutputBuilder builder = new GetAllQueuesStatisticsFromGivenPortOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } + + @Override + public Future> getQueueStatisticsFromGivenPort(GetQueueStatisticsFromGivenPortInput input) { + GetQueueStatisticsFromGivenPortOutputBuilder builder = new GetQueueStatisticsFromGivenPortOutputBuilder(); + TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet())); + builder.setTransactionId(transId); + QueueIdAndStatisticsMapBuilder qiasmBuilder = new QueueIdAndStatisticsMapBuilder(); + List queueIdAndStatisticsMaps = new ArrayList<>(); + qiasmBuilder.setKey(new QueueIdAndStatisticsMapKey(input.getNodeConnectorId(), input.getQueueId())); + qiasmBuilder.setTransmittedBytes(StatisticsManagerTest.COUNTER_64_TEST_VALUE); + queueIdAndStatisticsMaps.add(qiasmBuilder.build()); + QueueStatisticsUpdateBuilder qsuBuilder = new QueueStatisticsUpdateBuilder(); + qsuBuilder.setMoreReplies(false); + qsuBuilder.setTransactionId(transId); + qsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId()); + qsuBuilder.setQueueIdAndStatisticsMap(queueIdAndStatisticsMaps); + notifService.pushDelayedNotification(qsuBuilder.build(), 100); + return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build()); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/PortMockGenerator.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/PortMockGenerator.java new file mode 100644 index 0000000000..4c972173fb --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/PortMockGenerator.java @@ -0,0 +1,23 @@ +package test.mock.util; + + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.CommonPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.port.mod.port.Port; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.port.mod.port.PortBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.port.mod.port.PortKey; + +import java.util.Random; + +public class PortMockGenerator { + private static final Random rnd = new Random(); + private static final PortBuilder portBuilder = new PortBuilder(); + + public static Port getRandomPort() { + portBuilder.setKey(new PortKey(TestUtils.nextLong(0, 4294967295L))); + portBuilder.setBarrier(rnd.nextBoolean()); + portBuilder.setPortNumber(new CommonPort.PortNumber(TestUtils.nextLong(0, 4294967295L))); + portBuilder.setConfiguration(new PortConfig(rnd.nextBoolean(), rnd.nextBoolean(), rnd.nextBoolean(), rnd.nextBoolean())); + return portBuilder.build(); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java new file mode 100644 index 0000000000..9b40a7684f --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java @@ -0,0 +1,69 @@ +package test.mock.util; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.controller.sal.binding.api.BindingAwareService; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.RpcService; + +public class ProviderContextMock implements BindingAwareBroker.ProviderContext { + + RpcProviderRegistry rpcProviderMock; + NotificationProviderService notificationProviderService; + DataBroker dataBroker; + + public ProviderContextMock(RpcProviderRegistry rpcProviderMock, DataBroker dataBroker, + NotificationProviderService notificationProviderServiceMock) { + this.rpcProviderMock = rpcProviderMock; + this.dataBroker = dataBroker; + this.notificationProviderService = notificationProviderServiceMock; + } + + @Override + public void registerFunctionality(BindingAwareProvider.ProviderFunctionality functionality) { + + } + + @Override + public void unregisterFunctionality(BindingAwareProvider.ProviderFunctionality functionality) { + + } + + @SuppressWarnings("unchecked") + @Override + public T getSALService(Class service) { + if (service.equals(DataBroker.class)) { + return (T) dataBroker; + } + else if (service.equals(NotificationProviderService.class)) { + return (T) notificationProviderService; + } + return null; + } + + @Override + public BindingAwareBroker.RpcRegistration addRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { + return null; + } + + @Override + public BindingAwareBroker.RoutedRpcRegistration addRoutedRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { + return null; + } + + @Override + public >> ListenerRegistration registerRouteChangeListener(L listener) { + return null; + } + + @Override + public T getRpcService(Class serviceInterface) { + return rpcProviderMock.getRpcService(serviceInterface); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/QueueMockGenerator.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/QueueMockGenerator.java new file mode 100644 index 0000000000..f140776bf2 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/QueueMockGenerator.java @@ -0,0 +1,27 @@ +package test.mock.util; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId; + +import java.util.Random; + +public class QueueMockGenerator { + private static final Random rnd = new Random(); + private static final QueueBuilder queueBuilder = new QueueBuilder(); + + public static Queue getRandomQueue() { + queueBuilder.setKey(new QueueKey(new QueueId(TestUtils.nextLong(0, 4294967295L)))); + queueBuilder.setPort(TestUtils.nextLong(0, 4294967295L)); + queueBuilder.setProperty(rnd.nextInt(65535)); + return queueBuilder.build(); + } + + public static Queue getRandomQueueWithPortNum(long portNum) { + queueBuilder.setKey(new QueueKey(new QueueId(TestUtils.nextLong(0, 4294967295L)))); + queueBuilder.setPort(portNum); + queueBuilder.setProperty(rnd.nextInt(65535)); + return queueBuilder.build(); + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java new file mode 100644 index 0000000000..0b2548685e --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java @@ -0,0 +1,93 @@ +package test.mock.util; + +import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.RpcService; + +public class RpcProviderRegistryMock implements RpcProviderRegistry { + + OpendaylightFlowStatisticsServiceMock flowStatisticsServiceMock; + OpendaylightFlowTableStatisticsServiceMock flowTableStatisticsServiceMock; + OpendaylightGroupStatisticsServiceMock groupStatisticsServiceMock; + OpendaylightMeterStatisticsServiceMock meterStatisticsServiceMock; + OpendaylightPortStatisticsServiceMock portStatisticsServiceMock; + OpendaylightQueueStatisticsServiceMock queueStatisticsServiceMock; + + public RpcProviderRegistryMock(NotificationProviderServiceHelper notificationProviderService) { + this.flowStatisticsServiceMock = new OpendaylightFlowStatisticsServiceMock(notificationProviderService); + this.flowTableStatisticsServiceMock = new OpendaylightFlowTableStatisticsServiceMock(notificationProviderService); + this.groupStatisticsServiceMock = new OpendaylightGroupStatisticsServiceMock(notificationProviderService); + this.meterStatisticsServiceMock = new OpendaylightMeterStatisticsServiceMock(notificationProviderService); + this.portStatisticsServiceMock = new OpendaylightPortStatisticsServiceMock(notificationProviderService); + this.queueStatisticsServiceMock = new OpendaylightQueueStatisticsServiceMock(notificationProviderService); + } + + @Override + public BindingAwareBroker.RpcRegistration addRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { + return null; + } + + @Override + public BindingAwareBroker.RoutedRpcRegistration addRoutedRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { + return null; + } + + @Override + public >> ListenerRegistration registerRouteChangeListener(L listener) { + return null; + } + + @SuppressWarnings("unchecked") + @Override + public T getRpcService(Class serviceInterface) { + if (serviceInterface.equals(OpendaylightFlowStatisticsService.class)) { + return (T)flowStatisticsServiceMock; + } else if (serviceInterface.equals(OpendaylightFlowTableStatisticsService.class)) { + return (T) flowTableStatisticsServiceMock; + } else if (serviceInterface.equals(OpendaylightGroupStatisticsService.class)) { + return (T) groupStatisticsServiceMock; + } else if (serviceInterface.equals(OpendaylightMeterStatisticsService.class)) { + return (T) meterStatisticsServiceMock; + } else if (serviceInterface.equals(OpendaylightPortStatisticsService.class)) { + return (T) portStatisticsServiceMock; + } else if (serviceInterface.equals(OpendaylightQueueStatisticsService.class)) { + return (T) queueStatisticsServiceMock; + } else { + return null; + } + } + + public OpendaylightFlowStatisticsServiceMock getFlowStatisticsServiceMock() { + return flowStatisticsServiceMock; + } + + public OpendaylightFlowTableStatisticsServiceMock getFlowTableStatisticsServiceMock() { + return flowTableStatisticsServiceMock; + } + + public OpendaylightGroupStatisticsServiceMock getGroupStatisticsServiceMock() { + return groupStatisticsServiceMock; + } + + public OpendaylightMeterStatisticsServiceMock getMeterStatisticsServiceMock() { + return meterStatisticsServiceMock; + } + + public OpendaylightPortStatisticsServiceMock getPortStatisticsServiceMock() { + return portStatisticsServiceMock; + } + + public OpendaylightQueueStatisticsServiceMock getQueueStatisticsServiceMock() { + return queueStatisticsServiceMock; + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java new file mode 100644 index 0000000000..7f266d9c3c --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java @@ -0,0 +1,198 @@ +package test.mock.util; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeaturesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.port.mod.port.Port; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemovedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; + +public abstract class StatisticsManagerTest extends AbstractDataBrokerTest { + + public static final Counter64 COUNTER_64_TEST_VALUE = new Counter64(BigInteger.valueOf(128)); + public static final Counter32 COUNTER_32_TEST_VALUE = new Counter32(64L); + public static final Long MAX_GROUPS_TEST_VALUE = 2000L; + public static final BigInteger BIG_INTEGER_TEST_VALUE = BigInteger.valueOf(1000); + + private static Flow flow; + private static Group group; + private static Meter meter; + private static Port port; + private static Queue queue; + private static TableId tableId; + private static NodeConnectorId nodeConnectorId; + + private final NotificationProviderServiceHelper notificationMock = new NotificationProviderServiceHelper(); + protected final NodeKey s1Key = new NodeKey(new NodeId("S1")); + protected RpcProviderRegistryMock rpcRegistry; + protected ProviderContextMock providerContext; + + @BeforeClass + public static void setupTests() { + flow = FlowMockGenerator.getRandomFlow(); + group = GroupMockGenerator.getRandomGroup(); + meter = MeterMockGenerator.getRandomMeter(); + port = PortMockGenerator.getRandomPort(); + queue = QueueMockGenerator.getRandomQueueWithPortNum(port.getPortNumber().getUint32()); + tableId = new TableId((short) 2); + nodeConnectorId = new NodeConnectorId("connector.1"); + } + + @Before + public void init() { + rpcRegistry = new RpcProviderRegistryMock(notificationMock); + providerContext = new ProviderContextMock(rpcRegistry, getDataBroker(), notificationMock.getNotifBroker()); + } + + // node with statistics capabilities will enable cyclic statistics collection + @SafeVarargs + protected final void addFlowCapableNodeWithFeatures(final NodeKey nodeKey, final Boolean hasMeterCapabilities, + final Class... capabilities) + throws ExecutionException, InterruptedException { + final Nodes nodes = new NodesBuilder().setNode(Collections.emptyList()).build(); + final InstanceIdentifier flowNodeIdentifier = InstanceIdentifier.create(Nodes.class) + .child(Node.class, nodeKey); + + final FlowCapableNodeBuilder fcnBuilder = new FlowCapableNodeBuilder(); + final SwitchFeaturesBuilder sfBuilder = new SwitchFeaturesBuilder(); + final List> capabilitiyList = new ArrayList<>(); + for (final Class capability : capabilities) { + capabilitiyList.add(capability); + } + sfBuilder.setCapabilities(capabilitiyList); + sfBuilder.setMaxTables((short) 2); + final NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.setKey(nodeKey); + fcnBuilder.setSwitchFeatures(sfBuilder.build()); + final List
tables = new ArrayList<>(); + final TableBuilder tBuilder = new TableBuilder(); + tBuilder.setId(getFlow().getTableId()); + tables.add(tBuilder.build()); + fcnBuilder.setTable(tables); + final FlowCapableNode flowCapableNode = fcnBuilder.build(); + nodeBuilder.addAugmentation(FlowCapableNode.class, flowCapableNode); + final Node node = nodeBuilder.build(); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodes); + writeTx.put(LogicalDatastoreType.OPERATIONAL, flowNodeIdentifier, nodeBuilder.build()); + if (hasMeterCapabilities) { + final NodeMeterFeaturesBuilder nmfBuilder = new NodeMeterFeaturesBuilder(); + final MeterFeaturesBuilder mfBuilder = new MeterFeaturesBuilder(); + mfBuilder.setMaxBands((short) 4); + nmfBuilder.setMeterFeatures(mfBuilder.build()); + writeTx.put(LogicalDatastoreType.OPERATIONAL, flowNodeIdentifier.augmentation(NodeMeterFeatures.class), + nmfBuilder.build()); + } + writeTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Nodes.class), nodes); + writeTx.put(LogicalDatastoreType.CONFIGURATION, flowNodeIdentifier, node); + assertCommit(writeTx.submit()); + + final NodeUpdatedBuilder nuBuilder = new NodeUpdatedBuilder(node); + final FlowCapableNodeUpdatedBuilder fcnuBuilder = new FlowCapableNodeUpdatedBuilder(flowCapableNode); + nuBuilder.setNodeRef(new NodeRef(flowNodeIdentifier)); + nuBuilder.addAugmentation(FlowCapableNodeUpdated.class, fcnuBuilder.build()); + notificationMock.pushNotification(nuBuilder.build()); + } + + public void addFlowCapableNode(final NodeKey nodeKey) throws ExecutionException, InterruptedException { + final Nodes nodes = new NodesBuilder().setNode(Collections.emptyList()).build(); + final InstanceIdentifier flowNodeIdentifier = InstanceIdentifier.create(Nodes.class) + .child(Node.class, nodeKey); + + final FlowCapableNodeBuilder fcnBuilder = new FlowCapableNodeBuilder(); + final NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.setKey(nodeKey); + final FlowCapableNode flowCapableNode = fcnBuilder.build(); + nodeBuilder.addAugmentation(FlowCapableNode.class, flowCapableNode); + final Node node = nodeBuilder.build(); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodes); + writeTx.put(LogicalDatastoreType.OPERATIONAL, flowNodeIdentifier, node); + writeTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Nodes.class), nodes); + writeTx.put(LogicalDatastoreType.CONFIGURATION, flowNodeIdentifier, node); + assertCommit(writeTx.submit()); + + final NodeUpdatedBuilder nuBuilder = new NodeUpdatedBuilder(node); + final FlowCapableNodeUpdatedBuilder fcnuBuilder = new FlowCapableNodeUpdatedBuilder(flowCapableNode); + nuBuilder.setNodeRef(new NodeRef(flowNodeIdentifier)); + nuBuilder.addAugmentation(FlowCapableNodeUpdated.class, fcnuBuilder.build()); + notificationMock.pushNotification(nuBuilder.build()); + } + + protected void removeNode(final NodeKey nodeKey) throws ExecutionException, InterruptedException { + final InstanceIdentifier nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, nodeKey); + + final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.delete(LogicalDatastoreType.OPERATIONAL, nodeII); + writeTx.submit().get(); + + final NodeRemovedBuilder nrBuilder = new NodeRemovedBuilder(); + nrBuilder.setNodeRef(new NodeRef(nodeII)); + notificationMock.pushNotification(nrBuilder.build()); + } + + public static Flow getFlow() { + return flow; + } + + public static Group getGroup() { + return group; + } + + public static Meter getMeter() { + return meter; + } + + public static Port getPort() { + return port; + } + + public static Queue getQueue() { + return queue; + } + + public static TableId getTableId() { + return tableId; + } + + public static NodeConnectorId getNodeConnectorId() { + return nodeConnectorId; + } +} + diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java new file mode 100644 index 0000000000..e38a25e8e9 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java @@ -0,0 +1,11 @@ +package test.mock.util; + +import java.util.Random; + +public class TestUtils { + private static Random rnd = new Random(); + + public static long nextLong(long RangeBottom, long rangeTop) { + return RangeBottom + ((long)(rnd.nextDouble()*(rangeTop - RangeBottom))); + } +} -- 2.36.6