2 * Copyright IBM Corporation, 2013. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.md.statistics.manager;
10 import java.util.List;
11 import java.util.Timer;
12 import java.util.TimerTask;
13 import java.util.concurrent.TimeUnit;
15 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
16 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsDataBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatisticsBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFeatures;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFeatures;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.AggregateFlowStatistics;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 import com.google.common.base.Preconditions;
61 * This class handles the lifecycle of per-node statistics. It receives data
62 * from StatisticsListener, stores it in the data store and keeps track of
63 * when the data should be removed.
65 * @author avishnoi@in.ibm.com
67 public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableContext {
68 private static final Logger logger = LoggerFactory.getLogger(NodeStatisticsHandler.class);
70 private static final long STATS_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(15);
71 private static final long FIRST_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(5);
72 private static final int NUMBER_OF_WAIT_CYCLES = 2;
74 private final MultipartMessageManager msgManager;
75 private final StatisticsRequestScheduler srScheduler;
76 private final InstanceIdentifier<Node> targetNodeIdentifier;
77 private final FlowStatsTracker flowStats;
78 private final FlowTableStatsTracker flowTableStats;
79 private final GroupDescStatsTracker groupDescStats;
80 private final GroupStatsTracker groupStats;
81 private final MeterConfigStatsTracker meterConfigStats;
82 private final MeterStatsTracker meterStats;
83 private final NodeConnectorStatsTracker nodeConnectorStats;
84 private final QueueStatsTracker queueStats;
85 private final DataProviderService dps;
86 private final NodeRef targetNodeRef;
87 private final NodeKey targetNodeKey;
88 private final TimerTask task = new TimerTask() {
92 requestPeriodicStatistics();
93 cleanStaleStatistics();
95 logger.warn("Exception occured while sending statistics request : {}",e);
100 public NodeStatisticsHandler(final DataProviderService dps, final NodeKey nodeKey,
101 final OpendaylightFlowStatisticsService flowStatsService,
102 final OpendaylightFlowTableStatisticsService flowTableStatsService,
103 final OpendaylightGroupStatisticsService groupStatsService,
104 final OpendaylightMeterStatisticsService meterStatsService,
105 final OpendaylightPortStatisticsService portStatsService,
106 final OpendaylightQueueStatisticsService queueStatsService,
107 final StatisticsRequestScheduler srScheduler) {
108 this.dps = Preconditions.checkNotNull(dps);
109 this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
110 this.srScheduler = Preconditions.checkNotNull(srScheduler);
111 this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
112 this.targetNodeRef = new NodeRef(targetNodeIdentifier);
114 final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
116 msgManager = new MultipartMessageManager(lifetimeNanos);
117 flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this);
118 flowStats = new FlowStatsTracker(flowStatsService, this, flowTableStats);
119 groupDescStats = new GroupDescStatsTracker(groupStatsService, this);
120 groupStats = new GroupStatsTracker(groupStatsService, this);
121 meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this);
122 meterStats = new MeterStatsTracker(meterStatsService, this);
123 nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this);
124 queueStats = new QueueStatsTracker(queueStatsService, this);
127 public NodeKey getTargetNodeKey() {
128 return targetNodeKey;
132 public InstanceIdentifier<Node> getNodeIdentifier() {
133 return targetNodeIdentifier;
137 public NodeRef getNodeRef() {
138 return targetNodeRef;
142 public DataModificationTransaction startDataModification() {
143 DataModificationTransaction dmt = dps.beginTransaction();
144 dmt.registerListener(this.srScheduler);
148 public synchronized void updateGroupDescStats(TransactionAware transaction, List<GroupDescStats> list) {
149 if (msgManager.isExpectedTransaction(transaction)) {
150 groupDescStats.updateStats(list);
154 public synchronized void updateGroupStats(TransactionAware transaction, List<GroupStats> list) {
155 if (msgManager.isExpectedTransaction(transaction)) {
156 groupStats.updateStats(list);
160 public synchronized void updateMeterConfigStats(TransactionAware transaction, List<MeterConfigStats> list) {
161 if (msgManager.isExpectedTransaction(transaction)) {
162 meterConfigStats.updateStats(list);
166 public synchronized void updateMeterStats(TransactionAware transaction, List<MeterStats> list) {
167 if (msgManager.isExpectedTransaction(transaction)) {
168 meterStats.updateStats(list);
172 public synchronized void updateQueueStats(TransactionAware transaction, List<QueueIdAndStatisticsMap> list) {
173 if (msgManager.isExpectedTransaction(transaction)) {
174 queueStats.updateStats(list);
178 public synchronized void updateFlowTableStats(TransactionAware transaction, List<FlowTableAndStatisticsMap> list) {
179 if (msgManager.isExpectedTransaction(transaction)) {
180 flowTableStats.updateStats(list);
184 public synchronized void updateNodeConnectorStats(TransactionAware transaction, List<NodeConnectorStatisticsAndPortNumberMap> list) {
185 if (msgManager.isExpectedTransaction(transaction)) {
186 nodeConnectorStats.updateStats(list);
190 public synchronized void updateAggregateFlowStats(TransactionAware transaction, AggregateFlowStatistics flowStats) {
191 final Short tableId = msgManager.isExpectedTableTransaction(transaction);
192 if (tableId != null) {
193 final DataModificationTransaction trans = this.startDataModification();
194 InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
195 .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
197 AggregateFlowStatisticsDataBuilder aggregateFlowStatisticsDataBuilder = new AggregateFlowStatisticsDataBuilder();
198 AggregateFlowStatisticsBuilder aggregateFlowStatisticsBuilder = new AggregateFlowStatisticsBuilder(flowStats);
200 aggregateFlowStatisticsDataBuilder.setAggregateFlowStatistics(aggregateFlowStatisticsBuilder.build());
202 logger.debug("Augment aggregate statistics: {} for table {} on Node {}",
203 aggregateFlowStatisticsBuilder.build().toString(),tableId,targetNodeKey);
205 TableBuilder tableBuilder = new TableBuilder();
206 tableBuilder.setKey(new TableKey(tableId));
207 tableBuilder.addAugmentation(AggregateFlowStatisticsData.class, aggregateFlowStatisticsDataBuilder.build());
208 trans.putOperationalData(tableRef, tableBuilder.build());
214 public synchronized void updateFlowStats(TransactionAware transaction, List<FlowAndStatisticsMapList> list) {
215 if (msgManager.isExpectedTransaction(transaction)) {
216 flowStats.updateStats(list);
220 public synchronized void updateGroupFeatures(GroupFeatures notification) {
221 final DataModificationTransaction trans = this.startDataModification();
223 final NodeBuilder nodeData = new NodeBuilder();
224 nodeData.setKey(targetNodeKey);
226 NodeGroupFeaturesBuilder nodeGroupFeatures = new NodeGroupFeaturesBuilder();
227 GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder(notification);
228 nodeGroupFeatures.setGroupFeatures(groupFeatures.build());
230 //Update augmented data
231 nodeData.addAugmentation(NodeGroupFeatures.class, nodeGroupFeatures.build());
232 trans.putOperationalData(targetNodeIdentifier, nodeData.build());
234 // FIXME: should we be tracking this data?
238 public synchronized void updateMeterFeatures(MeterFeatures features) {
239 final DataModificationTransaction trans = this.startDataModification();
241 final NodeBuilder nodeData = new NodeBuilder();
242 nodeData.setKey(targetNodeKey);
244 NodeMeterFeaturesBuilder nodeMeterFeatures = new NodeMeterFeaturesBuilder();
245 MeterFeaturesBuilder meterFeature = new MeterFeaturesBuilder(features);
246 nodeMeterFeatures.setMeterFeatures(meterFeature.build());
248 //Update augmented data
249 nodeData.addAugmentation(NodeMeterFeatures.class, nodeMeterFeatures.build());
250 trans.putOperationalData(targetNodeIdentifier, nodeData.build());
252 // FIXME: should we be tracking this data?
256 public synchronized void cleanStaleStatistics() {
257 final DataModificationTransaction trans = this.startDataModification();
259 flowStats.cleanup(trans);
260 groupDescStats.cleanup(trans);
261 groupStats.cleanup(trans);
262 meterConfigStats.cleanup(trans);
263 meterStats.cleanup(trans);
264 nodeConnectorStats.cleanup(trans);
265 queueStats.cleanup(trans);
266 msgManager.cleanStaleTransactionIds();
271 public synchronized void requestPeriodicStatistics() {
272 logger.debug("Send requests for statistics collection to node : {}", targetNodeKey);
274 this.srScheduler.addRequestToSchedulerQueue(flowTableStats);
276 this.srScheduler.addRequestToSchedulerQueue(flowStats);
278 this.srScheduler.addRequestToSchedulerQueue(nodeConnectorStats);
280 this.srScheduler.addRequestToSchedulerQueue(groupStats);
282 this.srScheduler.addRequestToSchedulerQueue(groupDescStats);
284 this.srScheduler.addRequestToSchedulerQueue(meterStats);
286 this.srScheduler.addRequestToSchedulerQueue(meterConfigStats);
288 this.srScheduler.addRequestToSchedulerQueue(queueStats);
291 public synchronized void start(final Timer timer) {
292 flowStats.start(dps);
293 groupDescStats.start(dps);
294 groupStats.start(dps);
295 meterConfigStats.start(dps);
296 meterStats.start(dps);
297 queueStats.start(dps);
299 timer.schedule(task, (long) (Math.random() * FIRST_COLLECTION_MILLIS), STATS_COLLECTION_MILLIS);
301 logger.debug("Statistics handler for node started with base interval {}ms", STATS_COLLECTION_MILLIS);
303 requestPeriodicStatistics();
307 public synchronized void close() {
310 groupDescStats.close();
312 meterConfigStats.close();
316 //Clean up queued statistics request from scheduler queue
317 srScheduler.removeRequestsFromSchedulerQueue(this.getNodeRef());
319 logger.debug("Statistics handler for {} shut down", targetNodeKey.getId());
323 public void registerTransaction(TransactionId id) {
324 msgManager.recordExpectedTransaction(id);
325 logger.debug("Transaction {} for node {} sent successfully", id, targetNodeKey);
329 public void registerTableTransaction(final TransactionId id, final Short table) {
330 msgManager.recordExpectedTableTransaction(id, table);
331 logger.debug("Transaction {} for node {} table {} sent successfully", id, targetNodeKey, table);