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