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.Collection;
11 import java.util.List;
12 import java.util.concurrent.TimeUnit;
14 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
15 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsDataBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatisticsBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFeatures;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFeatures;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.AggregateFlowStatistics;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
57 import com.google.common.base.Preconditions;
60 * This class handles the lifecycle of per-node statistics. It receives data
61 * from StatisticsListener, stores it in the data store and keeps track of
62 * when the data should be removed.
64 * @author avishnoi@in.ibm.com
66 public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableContext {
67 private static final Logger logger = LoggerFactory.getLogger(NodeStatisticsHandler.class);
68 private static final int NUMBER_OF_WAIT_CYCLES = 2;
70 private final MultipartMessageManager msgManager = new MultipartMessageManager();
71 private final InstanceIdentifier<Node> targetNodeIdentifier;
72 private final FlowStatsTracker flowStats;
73 private final FlowTableStatsTracker flowTableStats;
74 private final GroupDescStatsTracker groupDescStats;
75 private final GroupStatsTracker groupStats;
76 private final MeterConfigStatsTracker meterConfigStats;
77 private final MeterStatsTracker meterStats;
78 private final NodeConnectorStatsTracker nodeConnectorStats;
79 private final QueueStatsTracker queueStats;
80 private final DataProviderService dps;
81 private final NodeRef targetNodeRef;
82 private final NodeKey targetNodeKey;
84 public NodeStatisticsHandler(final DataProviderService dps, final NodeKey nodeKey,
85 final OpendaylightFlowStatisticsService flowStatsService,
86 final OpendaylightFlowTableStatisticsService flowTableStatsService,
87 final OpendaylightGroupStatisticsService groupStatsService,
88 final OpendaylightMeterStatisticsService meterStatsService,
89 final OpendaylightPortStatisticsService portStatsService,
90 final OpendaylightQueueStatisticsService queueStatsService) {
91 this.dps = Preconditions.checkNotNull(dps);
92 this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
93 this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
94 this.targetNodeRef = new NodeRef(targetNodeIdentifier);
96 final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(StatisticsProvider.STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
98 flowStats = new FlowStatsTracker(flowStatsService, this, lifetimeNanos);
99 flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this, lifetimeNanos);
100 groupDescStats = new GroupDescStatsTracker(groupStatsService, this, lifetimeNanos);
101 groupStats = new GroupStatsTracker(groupStatsService, this, lifetimeNanos);
102 meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this, lifetimeNanos);
103 meterStats = new MeterStatsTracker(meterStatsService, this, lifetimeNanos);
104 nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this, lifetimeNanos);
105 queueStats = new QueueStatsTracker(queueStatsService, this, lifetimeNanos);
108 public NodeKey getTargetNodeKey() {
109 return targetNodeKey;
113 public InstanceIdentifier<Node> getNodeIdentifier() {
114 return targetNodeIdentifier;
118 public NodeRef getNodeRef() {
119 return targetNodeRef;
123 public DataModificationTransaction startDataModification() {
124 return dps.beginTransaction();
127 public synchronized void updateGroupDescStats(TransactionAware transaction, Boolean more, List<GroupDescStats> list) {
128 if (msgManager.isExpectedTransaction(transaction, more)) {
129 groupDescStats.updateStats(list);
133 public synchronized void updateGroupStats(TransactionAware transaction, Boolean more, List<GroupStats> list) {
134 if (msgManager.isExpectedTransaction(transaction, more)) {
135 groupStats.updateStats(list);
139 public synchronized void updateMeterConfigStats(TransactionAware transaction, Boolean more, List<MeterConfigStats> list) {
140 if (msgManager.isExpectedTransaction(transaction, more)) {
141 meterConfigStats.updateStats(list);
145 public synchronized void updateMeterStats(TransactionAware transaction, Boolean more, List<MeterStats> list) {
146 if (msgManager.isExpectedTransaction(transaction, more)) {
147 meterStats.updateStats(list);
151 public synchronized void updateQueueStats(TransactionAware transaction, Boolean more, List<QueueIdAndStatisticsMap> list) {
152 if (msgManager.isExpectedTransaction(transaction, more)) {
153 queueStats.updateStats(list);
157 public synchronized void updateFlowTableStats(TransactionAware transaction, Boolean more, List<FlowTableAndStatisticsMap> list) {
158 if (msgManager.isExpectedTransaction(transaction, more)) {
159 flowTableStats.updateStats(list);
163 public synchronized void updateNodeConnectorStats(TransactionAware transaction, Boolean more, List<NodeConnectorStatisticsAndPortNumberMap> list) {
164 if (msgManager.isExpectedTransaction(transaction, more)) {
165 nodeConnectorStats.updateStats(list);
169 public synchronized void updateAggregateFlowStats(TransactionAware transaction, Boolean more, AggregateFlowStatistics flowStats) {
170 final Short tableId = msgManager.isExpectedTableTransaction(transaction, more);
171 if (tableId != null) {
172 final DataModificationTransaction trans = dps.beginTransaction();
173 InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
174 .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
176 AggregateFlowStatisticsDataBuilder aggregateFlowStatisticsDataBuilder = new AggregateFlowStatisticsDataBuilder();
177 AggregateFlowStatisticsBuilder aggregateFlowStatisticsBuilder = new AggregateFlowStatisticsBuilder(flowStats);
179 aggregateFlowStatisticsDataBuilder.setAggregateFlowStatistics(aggregateFlowStatisticsBuilder.build());
181 logger.debug("Augment aggregate statistics: {} for table {} on Node {}",
182 aggregateFlowStatisticsBuilder.build().toString(),tableId,targetNodeKey);
184 TableBuilder tableBuilder = new TableBuilder();
185 tableBuilder.setKey(new TableKey(tableId));
186 tableBuilder.addAugmentation(AggregateFlowStatisticsData.class, aggregateFlowStatisticsDataBuilder.build());
187 trans.putOperationalData(tableRef, tableBuilder.build());
193 public synchronized void updateFlowStats(TransactionAware transaction, Boolean more, List<FlowAndStatisticsMapList> list) {
194 if (msgManager.isExpectedTransaction(transaction, more)) {
195 flowStats.updateStats(list);
199 public synchronized void updateGroupFeatures(GroupFeatures notification) {
200 final DataModificationTransaction trans = dps.beginTransaction();
202 final NodeBuilder nodeData = new NodeBuilder();
203 nodeData.setKey(targetNodeKey);
205 NodeGroupFeaturesBuilder nodeGroupFeatures = new NodeGroupFeaturesBuilder();
206 GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder(notification);
207 nodeGroupFeatures.setGroupFeatures(groupFeatures.build());
209 //Update augmented data
210 nodeData.addAugmentation(NodeGroupFeatures.class, nodeGroupFeatures.build());
211 trans.putOperationalData(targetNodeIdentifier, nodeData.build());
213 // FIXME: should we be tracking this data?
217 public synchronized void updateMeterFeatures(MeterFeatures features) {
218 final DataModificationTransaction trans = dps.beginTransaction();
220 final NodeBuilder nodeData = new NodeBuilder();
221 nodeData.setKey(targetNodeKey);
223 NodeMeterFeaturesBuilder nodeMeterFeatures = new NodeMeterFeaturesBuilder();
224 MeterFeaturesBuilder meterFeature = new MeterFeaturesBuilder(features);
225 nodeMeterFeatures.setMeterFeatures(meterFeature.build());
227 //Update augmented data
228 nodeData.addAugmentation(NodeMeterFeatures.class, nodeMeterFeatures.build());
229 trans.putOperationalData(targetNodeIdentifier, nodeData.build());
231 // FIXME: should we be tracking this data?
235 public synchronized void cleanStaleStatistics() {
236 final DataModificationTransaction trans = dps.beginTransaction();
237 final long now = System.nanoTime();
239 flowStats.cleanup(trans, now);
240 groupDescStats.cleanup(trans, now);
241 groupStats.cleanup(trans, now);
242 meterConfigStats.cleanup(trans, now);
243 meterStats.cleanup(trans, now);
244 nodeConnectorStats.cleanup(trans, now);
245 queueStats.cleanup(trans, now);
246 msgManager.cleanStaleTransactionIds();
251 public synchronized void requestPeriodicStatistics() {
252 logger.debug("Send requests for statistics collection to node : {}", targetNodeKey);
254 flowTableStats.request();
256 // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
257 // comes back -- we do not have any tables anyway.
258 final Collection<TableKey> tables = flowTableStats.getTables();
259 logger.debug("Node {} supports {} table(s)", targetNodeKey, tables.size());
260 for (final TableKey key : tables) {
261 logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), targetNodeKey);
262 flowStats.requestAggregateFlows(key);
265 flowStats.requestAllFlowsAllTables();
266 nodeConnectorStats.request();
267 groupStats.request();
268 groupDescStats.request();
269 meterStats.request();
270 meterConfigStats.request();
271 queueStats.request();
274 public synchronized void start() {
275 flowStats.start(dps);
276 groupDescStats.start(dps);
277 groupStats.start(dps);
278 meterConfigStats.start(dps);
279 meterStats.start(dps);
280 queueStats.start(dps);
282 requestPeriodicStatistics();
286 public synchronized void close() {
288 groupDescStats.close();
290 meterConfigStats.close();
294 logger.debug("Statistics handler for {} shut down", targetNodeKey.getId());
298 public void registerTransaction(TransactionId id) {
299 msgManager.recordExpectedTransaction(id);
300 logger.debug("Transaction {} for node {} sent successfully", id, targetNodeKey);
304 public void registerTableTransaction(final TransactionId id, final Short table) {
305 msgManager.recordExpectedTableTransaction(id, table);
306 logger.debug("Transaction {} for node {} table {} sent successfully", id, targetNodeKey, table);