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.Date;
11 import java.util.Iterator;
12 import java.util.List;
14 import java.util.concurrent.ConcurrentHashMap;
16 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
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.FlowCapableNodeConnector;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
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.NodeMeterConfigStats;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
43 import org.opendaylight.yangtools.yang.binding.DataObject;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
48 * Main responsibility of this class to clean up all the stale statistics data
49 * associated to Flow,Meter,Group,Queue.
50 * @author avishnoi@in.ibm.com
53 public class NodeStatisticsAger {
55 private final int NUMBER_OF_WAIT_CYCLES =2;
57 private final StatisticsProvider statisticsProvider;
59 private final NodeKey targetNodeKey;
61 private final Map<GroupDescStats,Date> groupDescStatsUpdate
62 = new ConcurrentHashMap<GroupDescStats,Date>();
64 private final Map<MeterConfigStats,Date> meterConfigStatsUpdate
65 = new ConcurrentHashMap<MeterConfigStats,Date>();
67 private final Map<FlowEntry,Date> flowStatsUpdate
68 = new ConcurrentHashMap<FlowEntry,Date>();
70 private final Map<QueueEntry,Date> queuesStatsUpdate
71 = new ConcurrentHashMap<QueueEntry,Date>();
73 public NodeStatisticsAger(StatisticsProvider statisticsProvider, NodeKey nodeKey){
74 this.targetNodeKey = nodeKey;
75 this.statisticsProvider = statisticsProvider;
78 public class FlowEntry{
79 private final Short tableId;
80 private final Flow flow;
82 public FlowEntry(Short tableId, Flow flow){
83 this.tableId = tableId;
87 public Short getTableId() {
91 public Flow getFlow() {
96 public int hashCode() {
99 result = prime * result + getOuterType().hashCode();
100 result = prime * result + ((flow == null) ? 0 : flow.hashCode());
101 result = prime * result + ((tableId == null) ? 0 : tableId.hashCode());
106 public boolean equals(Object obj) {
111 if (getClass() != obj.getClass())
113 FlowEntry other = (FlowEntry) obj;
114 if (!getOuterType().equals(other.getOuterType()))
117 if (other.flow != null)
119 } else if (!flow.equals(other.flow))
121 if (tableId == null) {
122 if (other.tableId != null)
124 } else if (!tableId.equals(other.tableId))
129 private NodeStatisticsAger getOuterType() {
130 return NodeStatisticsAger.this;
135 public class QueueEntry{
136 private final NodeConnectorId nodeConnectorId;
137 private final QueueId queueId;
138 public QueueEntry(NodeConnectorId ncId, QueueId queueId){
139 this.nodeConnectorId = ncId;
140 this.queueId = queueId;
142 public NodeConnectorId getNodeConnectorId() {
143 return nodeConnectorId;
145 public QueueId getQueueId() {
149 public int hashCode() {
150 final int prime = 31;
152 result = prime * result + getOuterType().hashCode();
153 result = prime * result + ((nodeConnectorId == null) ? 0 : nodeConnectorId.hashCode());
154 result = prime * result + ((queueId == null) ? 0 : queueId.hashCode());
158 public boolean equals(Object obj) {
165 if (!(obj instanceof QueueEntry)) {
168 QueueEntry other = (QueueEntry) obj;
169 if (!getOuterType().equals(other.getOuterType())) {
172 if (nodeConnectorId == null) {
173 if (other.nodeConnectorId != null) {
176 } else if (!nodeConnectorId.equals(other.nodeConnectorId)) {
179 if (queueId == null) {
180 if (other.queueId != null) {
183 } else if (!queueId.equals(other.queueId)) {
188 private NodeStatisticsAger getOuterType() {
189 return NodeStatisticsAger.this;
193 public NodeKey getTargetNodeKey() {
194 return targetNodeKey;
197 public Map<GroupDescStats, Date> getGroupDescStatsUpdate() {
198 return groupDescStatsUpdate;
201 public Map<MeterConfigStats, Date> getMeterConfigStatsUpdate() {
202 return meterConfigStatsUpdate;
205 public Map<FlowEntry, Date> getFlowStatsUpdate() {
206 return flowStatsUpdate;
209 public Map<QueueEntry, Date> getQueuesStatsUpdate() {
210 return queuesStatsUpdate;
213 public void updateGroupDescStats(List<GroupDescStats> list){
214 Date expiryTime = getExpiryTime();
215 for(GroupDescStats groupDescStats : list)
216 this.groupDescStatsUpdate.put(groupDescStats, expiryTime);
219 public void updateMeterConfigStats(List<MeterConfigStats> list){
220 Date expiryTime = getExpiryTime();
221 for(MeterConfigStats meterConfigStats: list)
222 this.meterConfigStatsUpdate.put(meterConfigStats, expiryTime);
225 public void updateFlowStats(FlowEntry flowEntry){
226 this.flowStatsUpdate.put(flowEntry, getExpiryTime());
228 public void updateQueueStats(QueueEntry queueEntry){
229 this.queuesStatsUpdate.put(queueEntry, getExpiryTime());
232 private Date getExpiryTime(){
233 Date expires = new Date();
234 expires.setTime(expires.getTime()+StatisticsProvider.STATS_THREAD_EXECUTION_TIME*NUMBER_OF_WAIT_CYCLES);
238 public void cleanStaleStatistics(){
239 //Clean stale statistics related to group
240 for (Iterator<GroupDescStats> it = this.groupDescStatsUpdate.keySet().iterator();it.hasNext();){
241 GroupDescStats groupDescStats = it.next();
242 Date now = new Date();
243 Date expiryTime = this.groupDescStatsUpdate.get(groupDescStats);
244 if(now.after(expiryTime)){
245 cleanGroupStatsFromDataStore(groupDescStats );
250 //Clean stale statistics related to meter
251 for (Iterator<MeterConfigStats> it = this.meterConfigStatsUpdate.keySet().iterator();it.hasNext();){
252 MeterConfigStats meterConfigStats = it.next();
253 Date now = new Date();
254 Date expiryTime = this.meterConfigStatsUpdate.get(meterConfigStats);
255 if(now.after(expiryTime)){
256 cleanMeterStatsFromDataStore(meterConfigStats);
261 //Clean stale statistics related to flow
262 for (Iterator<FlowEntry> it = this.flowStatsUpdate.keySet().iterator();it.hasNext();){
263 FlowEntry flowEntry = it.next();
264 Date now = new Date();
265 Date expiryTime = this.flowStatsUpdate.get(flowEntry);
266 if(now.after(expiryTime)){
267 cleanFlowStatsFromDataStore(flowEntry);
272 //Clean stale statistics related to queue
273 for (Iterator<QueueEntry> it = this.queuesStatsUpdate.keySet().iterator();it.hasNext();){
274 QueueEntry queueEntry = it.next();
275 Date now = new Date();
276 Date expiryTime = this.queuesStatsUpdate.get(queueEntry);
277 if(now.after(expiryTime)){
278 cleanQueueStatsFromDataStore(queueEntry);
285 private void cleanQueueStatsFromDataStore(QueueEntry queueEntry) {
286 InstanceIdentifier<?> queueRef
287 = InstanceIdentifier.builder(Nodes.class)
288 .child(Node.class, this.targetNodeKey)
289 .child(NodeConnector.class, new NodeConnectorKey(queueEntry.getNodeConnectorId()))
290 .augmentation(FlowCapableNodeConnector.class)
291 .child(Queue.class, new QueueKey(queueEntry.getQueueId()))
292 .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).toInstance();
293 cleanStaleStatisticsFromDataStore(queueRef);
296 private void cleanFlowStatsFromDataStore(FlowEntry flowEntry) {
297 InstanceIdentifier<?> flowRef
298 = InstanceIdentifier.builder(Nodes.class).child(Node.class, this.targetNodeKey)
299 .augmentation(FlowCapableNode.class)
300 .child(Table.class, new TableKey(flowEntry.getTableId()))
301 .child(Flow.class,flowEntry.getFlow().getKey())
302 .augmentation(FlowStatisticsData.class).toInstance();
304 cleanStaleStatisticsFromDataStore(flowRef);
308 private void cleanMeterStatsFromDataStore(MeterConfigStats meterConfigStats) {
309 InstanceIdentifierBuilder<Meter> meterRef
310 = InstanceIdentifier.builder(Nodes.class).child(Node.class,this.targetNodeKey)
311 .augmentation(FlowCapableNode.class)
312 .child(Meter.class,new MeterKey(meterConfigStats.getMeterId()));
314 InstanceIdentifier<?> nodeMeterConfigStatsAugmentation = meterRef.augmentation(NodeMeterConfigStats.class).toInstance();
316 cleanStaleStatisticsFromDataStore(nodeMeterConfigStatsAugmentation);
318 InstanceIdentifier<?> nodeMeterStatisticsAugmentation = meterRef.augmentation(NodeMeterStatistics.class).toInstance();
320 cleanStaleStatisticsFromDataStore(nodeMeterStatisticsAugmentation);
324 private void cleanGroupStatsFromDataStore(GroupDescStats groupDescStats) {
325 InstanceIdentifierBuilder<Group> groupRef
326 = InstanceIdentifier.builder(Nodes.class).child(Node.class,this.targetNodeKey)
327 .augmentation(FlowCapableNode.class)
328 .child(Group.class,new GroupKey(groupDescStats.getGroupId()));
330 InstanceIdentifier<?> nodeGroupDescStatsAugmentation = groupRef.augmentation(NodeGroupDescStats.class).toInstance();
332 cleanStaleStatisticsFromDataStore(nodeGroupDescStatsAugmentation);
334 InstanceIdentifier<?> nodeGroupStatisticsAugmentation = groupRef.augmentation(NodeGroupStatistics.class).toInstance();
336 cleanStaleStatisticsFromDataStore(nodeGroupStatisticsAugmentation);
339 private void cleanStaleStatisticsFromDataStore(InstanceIdentifier<? extends DataObject> ii){
341 DataModificationTransaction it = this.statisticsProvider.startChange();
342 it.removeOperationalData(ii);