Fixed bug when Binding-Aware Data Change Listeners we're not triggered.
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / NodeStatisticsAger.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.Date;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.ConcurrentHashMap;
15
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;
46
47 /**
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
51  *
52  */
53 public class NodeStatisticsAger {
54     
55     private final int NUMBER_OF_WAIT_CYCLES =2;
56
57     private final StatisticsProvider statisticsProvider;
58
59     private final NodeKey targetNodeKey;
60     
61     private final Map<GroupDescStats,Date> groupDescStatsUpdate
62                 = new ConcurrentHashMap<GroupDescStats,Date>();
63     
64     private final Map<MeterConfigStats,Date> meterConfigStatsUpdate
65                 = new ConcurrentHashMap<MeterConfigStats,Date>();
66     
67     private final Map<FlowEntry,Date> flowStatsUpdate
68                 = new ConcurrentHashMap<FlowEntry,Date>();
69     
70     private final Map<QueueEntry,Date> queuesStatsUpdate 
71                 = new ConcurrentHashMap<QueueEntry,Date>();
72     
73     public NodeStatisticsAger(StatisticsProvider statisticsProvider, NodeKey nodeKey){
74         this.targetNodeKey = nodeKey;
75         this.statisticsProvider = statisticsProvider;
76     }
77
78     public class FlowEntry{
79         private final Short tableId;
80         private final Flow flow;
81         
82         public FlowEntry(Short tableId, Flow flow){
83             this.tableId = tableId;
84             this.flow = flow;
85         }
86
87         public Short getTableId() {
88             return tableId;
89         }
90
91         public Flow getFlow() {
92             return flow;
93         }
94
95         @Override
96         public int hashCode() {
97             final int prime = 31;
98             int result = 1;
99             result = prime * result + getOuterType().hashCode();
100             result = prime * result + ((flow == null) ? 0 : flow.hashCode());
101             result = prime * result + ((tableId == null) ? 0 : tableId.hashCode());
102             return result;
103         }
104
105         @Override
106         public boolean equals(Object obj) {
107             if (this == obj)
108                 return true;
109             if (obj == null)
110                 return false;
111             if (getClass() != obj.getClass())
112                 return false;
113             FlowEntry other = (FlowEntry) obj;
114             if (!getOuterType().equals(other.getOuterType()))
115                 return false;
116             if (flow == null) {
117                 if (other.flow != null)
118                     return false;
119             } else if (!flow.equals(other.flow))
120                 return false;
121             if (tableId == null) {
122                 if (other.tableId != null)
123                     return false;
124             } else if (!tableId.equals(other.tableId))
125                 return false;
126             return true;
127         }
128
129         private NodeStatisticsAger getOuterType() {
130             return NodeStatisticsAger.this;
131         }
132         
133     }
134     
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;
141         }
142         public NodeConnectorId getNodeConnectorId() {
143             return nodeConnectorId;
144         }
145         public QueueId getQueueId() {
146             return queueId;
147         }
148         @Override
149         public int hashCode() {
150             final int prime = 31;
151             int result = 1;
152             result = prime * result + getOuterType().hashCode();
153             result = prime * result + ((nodeConnectorId == null) ? 0 : nodeConnectorId.hashCode());
154             result = prime * result + ((queueId == null) ? 0 : queueId.hashCode());
155             return result;
156         }
157         @Override
158         public boolean equals(Object obj) {
159             if (this == obj) {
160                 return true;
161             }
162             if (obj == null) {
163                 return false;
164             }
165             if (!(obj instanceof QueueEntry)) {
166                 return false;
167             }
168             QueueEntry other = (QueueEntry) obj;
169             if (!getOuterType().equals(other.getOuterType())) {
170                 return false;
171             }
172             if (nodeConnectorId == null) {
173                 if (other.nodeConnectorId != null) {
174                     return false;
175                 }
176             } else if (!nodeConnectorId.equals(other.nodeConnectorId)) {
177                 return false;
178             }
179             if (queueId == null) {
180                 if (other.queueId != null) {
181                     return false;
182                 }
183             } else if (!queueId.equals(other.queueId)) {
184                 return false;
185             }
186             return true;
187         }
188         private NodeStatisticsAger getOuterType() {
189             return NodeStatisticsAger.this;
190         }
191     }
192     
193     public NodeKey getTargetNodeKey() {
194         return targetNodeKey;
195     }
196
197     public Map<GroupDescStats, Date> getGroupDescStatsUpdate() {
198         return groupDescStatsUpdate;
199     }
200
201     public Map<MeterConfigStats, Date> getMeterConfigStatsUpdate() {
202         return meterConfigStatsUpdate;
203     }
204
205     public Map<FlowEntry, Date> getFlowStatsUpdate() {
206         return flowStatsUpdate;
207     }
208
209     public Map<QueueEntry, Date> getQueuesStatsUpdate() {
210         return queuesStatsUpdate;
211     }
212
213     public void updateGroupDescStats(List<GroupDescStats> list){
214         Date expiryTime = getExpiryTime();
215         for(GroupDescStats groupDescStats : list)
216             this.groupDescStatsUpdate.put(groupDescStats, expiryTime);
217     }
218     
219     public void updateMeterConfigStats(List<MeterConfigStats> list){
220         Date expiryTime = getExpiryTime();
221         for(MeterConfigStats meterConfigStats: list)
222             this.meterConfigStatsUpdate.put(meterConfigStats, expiryTime);
223     }
224     
225     public void  updateFlowStats(FlowEntry flowEntry){
226         this.flowStatsUpdate.put(flowEntry, getExpiryTime());
227     }
228     public void updateQueueStats(QueueEntry queueEntry){
229         this.queuesStatsUpdate.put(queueEntry, getExpiryTime());
230     }
231     
232     private Date getExpiryTime(){
233         Date expires = new Date();
234         expires.setTime(expires.getTime()+StatisticsProvider.STATS_THREAD_EXECUTION_TIME*NUMBER_OF_WAIT_CYCLES);
235         return expires;
236     }
237     
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 );
246                 it.remove();
247             }
248         }
249         
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);
257                 it.remove();
258             }            
259         }
260         
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);
268                 it.remove();
269             }            
270         }
271
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);
279                 it.remove();
280             }            
281         }
282         
283     }
284
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);
294     }
295
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();
303         
304         cleanStaleStatisticsFromDataStore(flowRef);
305         
306     }
307
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()));
313         
314         InstanceIdentifier<?> nodeMeterConfigStatsAugmentation = meterRef.augmentation(NodeMeterConfigStats.class).toInstance();
315                                             
316         cleanStaleStatisticsFromDataStore(nodeMeterConfigStatsAugmentation);
317         
318         InstanceIdentifier<?> nodeMeterStatisticsAugmentation = meterRef.augmentation(NodeMeterStatistics.class).toInstance();
319         
320         cleanStaleStatisticsFromDataStore(nodeMeterStatisticsAugmentation);
321         
322     }
323
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()));
329         
330         InstanceIdentifier<?> nodeGroupDescStatsAugmentation = groupRef.augmentation(NodeGroupDescStats.class).toInstance();
331         
332         cleanStaleStatisticsFromDataStore(nodeGroupDescStatsAugmentation);
333
334         InstanceIdentifier<?> nodeGroupStatisticsAugmentation = groupRef.augmentation(NodeGroupStatistics.class).toInstance();
335         
336         cleanStaleStatisticsFromDataStore(nodeGroupStatisticsAugmentation);
337     }
338     
339     private void cleanStaleStatisticsFromDataStore(InstanceIdentifier<? extends DataObject> ii){
340         if(ii != null){
341             DataModificationTransaction it = this.statisticsProvider.startChange();
342             it.removeOperationalData(ii);
343             it.commit();
344         }
345     }
346 }