Split out statistics tracking into separate classes
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / NodeStatisticsHandler.java
1 /*
2  * Copyright IBM Corporation, 2013.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.md.statistics.manager;
9
10 import java.util.Collection;
11 import java.util.List;
12 import java.util.concurrent.TimeUnit;
13
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.aggregate.flow.statistics.AggregateFlowStatisticsBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFeatures;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFeatures;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.AggregateFlowStatistics;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import com.google.common.base.Preconditions;
50
51 /**
52  * This class handles the lifecycle of per-node statistics. It receives data
53  * from StatisticsListener, stores it in the data store and keeps track of
54  * when the data should be removed.
55  *
56  * @author avishnoi@in.ibm.com
57  */
58 public final class NodeStatisticsHandler implements AutoCloseable {
59     private static final Logger logger = LoggerFactory.getLogger(NodeStatisticsHandler.class);
60     private static final int NUMBER_OF_WAIT_CYCLES = 2;
61
62     private final InstanceIdentifier<Node> targetNodeIdentifier;
63     private final FlowStatsTracker flowStats;
64     private final FlowTableStatsTracker flowTableStats;
65     private final GroupDescStatsTracker groupDescStats;
66     private final GroupStatsTracker groupStats;
67     private final MeterConfigStatsTracker meterConfigStats;
68     private final MeterStatsTracker meterStats;
69     private final NodeConnectorStatsTracker nodeConnectorStats;
70     private final QueueStatsTracker queueStats;
71     private final DataProviderService dps;
72     private final NodeRef targetNodeRef;
73     private final NodeKey targetNodeKey;
74
75     public NodeStatisticsHandler(final DataProviderService dps, final NodeKey nodeKey) {
76         this.dps = Preconditions.checkNotNull(dps);
77         this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
78         this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
79         this.targetNodeRef = new NodeRef(targetNodeIdentifier);
80
81         final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(StatisticsProvider.STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
82         flowStats = new FlowStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
83         flowTableStats = new FlowTableStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
84         groupDescStats = new GroupDescStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
85         groupStats = new GroupStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
86         meterConfigStats = new MeterConfigStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
87         meterStats = new MeterStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
88         nodeConnectorStats = new NodeConnectorStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
89         queueStats = new QueueStatsTracker(targetNodeIdentifier, dps, lifetimeNanos);
90     }
91
92     public NodeKey getTargetNodeKey() {
93         return targetNodeKey;
94     }
95
96     public Collection<TableKey> getKnownTables() {
97         return flowTableStats.getTables();
98     }
99
100     public InstanceIdentifier<Node> getTargetNodeIdentifier() {
101         return targetNodeIdentifier;
102     }
103
104     public NodeRef getTargetNodeRef() {
105         return targetNodeRef;
106     }
107
108     public synchronized void updateGroupDescStats(List<GroupDescStats> list) {
109         groupDescStats.updateStats(list);
110     }
111
112     public synchronized void updateGroupStats(List<GroupStats> list) {
113         groupStats.updateStats(list);
114     }
115
116     public synchronized void updateMeterConfigStats(List<MeterConfigStats> list) {
117         meterConfigStats.updateStats(list);
118     }
119
120     public synchronized void updateMeterStats(List<MeterStats> list) {
121         meterStats.updateStats(list);
122     }
123
124     public synchronized void updateQueueStats(List<QueueIdAndStatisticsMap> list) {
125         queueStats.updateStats(list);
126     }
127
128     public synchronized void updateFlowTableStats(List<FlowTableAndStatisticsMap> list) {
129         flowTableStats.updateStats(list);
130     }
131
132     public synchronized void updateNodeConnectorStats(List<NodeConnectorStatisticsAndPortNumberMap> list) {
133         nodeConnectorStats.updateStats(list);
134     }
135
136     public synchronized void updateAggregateFlowStats(Short tableId, AggregateFlowStatistics flowStats) {
137         if (tableId != null) {
138             final DataModificationTransaction trans = dps.beginTransaction();
139
140             InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
141                     .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
142
143             AggregateFlowStatisticsDataBuilder aggregateFlowStatisticsDataBuilder = new AggregateFlowStatisticsDataBuilder();
144             AggregateFlowStatisticsBuilder aggregateFlowStatisticsBuilder = new AggregateFlowStatisticsBuilder(flowStats);
145
146             aggregateFlowStatisticsDataBuilder.setAggregateFlowStatistics(aggregateFlowStatisticsBuilder.build());
147
148             logger.debug("Augment aggregate statistics: {} for table {} on Node {}",
149                     aggregateFlowStatisticsBuilder.build().toString(),tableId,targetNodeKey);
150
151             TableBuilder tableBuilder = new TableBuilder();
152             tableBuilder.setKey(new TableKey(tableId));
153             tableBuilder.addAugmentation(AggregateFlowStatisticsData.class, aggregateFlowStatisticsDataBuilder.build());
154             trans.putOperationalData(tableRef, tableBuilder.build());
155
156             // FIXME: should we be tracking this data?
157             trans.commit();
158         }
159     }
160
161     public synchronized void updateGroupFeatures(GroupFeatures notification) {
162         final DataModificationTransaction trans = dps.beginTransaction();
163
164         final NodeBuilder nodeData = new NodeBuilder();
165         nodeData.setKey(targetNodeKey);
166
167         NodeGroupFeaturesBuilder nodeGroupFeatures = new NodeGroupFeaturesBuilder();
168         GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder(notification);
169         nodeGroupFeatures.setGroupFeatures(groupFeatures.build());
170
171         //Update augmented data
172         nodeData.addAugmentation(NodeGroupFeatures.class, nodeGroupFeatures.build());
173         trans.putOperationalData(targetNodeIdentifier, nodeData.build());
174
175         // FIXME: should we be tracking this data?
176         trans.commit();
177     }
178
179     public synchronized void updateMeterFeatures(MeterFeatures features) {
180         final DataModificationTransaction trans = dps.beginTransaction();
181
182         final NodeBuilder nodeData = new NodeBuilder();
183         nodeData.setKey(targetNodeKey);
184
185         NodeMeterFeaturesBuilder nodeMeterFeatures = new NodeMeterFeaturesBuilder();
186         MeterFeaturesBuilder meterFeature = new MeterFeaturesBuilder(features);
187         nodeMeterFeatures.setMeterFeatures(meterFeature.build());
188
189         //Update augmented data
190         nodeData.addAugmentation(NodeMeterFeatures.class, nodeMeterFeatures.build());
191         trans.putOperationalData(targetNodeIdentifier, nodeData.build());
192
193         // FIXME: should we be tracking this data?
194         trans.commit();
195     }
196
197     public synchronized void updateFlowStats(List<FlowAndStatisticsMapList> list) {
198         flowStats.updateStats(list);
199     }
200
201     public synchronized void cleanStaleStatistics() {
202         final DataModificationTransaction trans = dps.beginTransaction();
203         final long now = System.nanoTime();
204
205         flowStats.cleanup(trans, now);
206         groupDescStats.cleanup(trans, now);
207         groupStats.cleanup(trans, now);
208         meterConfigStats.cleanup(trans, now);
209         meterStats.cleanup(trans, now);
210         nodeConnectorStats.cleanup(trans, now);
211         queueStats.cleanup(trans, now);
212
213         trans.commit();
214     }
215
216     @Override
217     public void close() {
218         // FIXME: cleanup any resources we hold (registrations, etc.)
219         logger.debug("Statistics handler for {} shut down", targetNodeKey.getId());
220     }
221 }