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.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
14 import java.util.Map.Entry;
15 import java.util.concurrent.TimeUnit;
17 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
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.NodeKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
47 import com.google.common.base.Preconditions;
50 * Main responsibility of this class to clean up all the stale statistics data
51 * associated to Flow,Meter,Group,Queue.
52 * @author avishnoi@in.ibm.com
55 public class NodeStatisticsAger {
56 private static final int NUMBER_OF_WAIT_CYCLES = 2;
58 private final Map<GroupDescStats,Long> groupDescStatsUpdate = new HashMap<>();
59 private final Map<MeterConfigStats,Long> meterConfigStatsUpdate = new HashMap<>();
60 private final Map<FlowEntry,Long> flowStatsUpdate = new HashMap<>();
61 private final Map<QueueEntry,Long> queuesStatsUpdate = new HashMap<>();
62 private final StatisticsProvider statisticsProvider;
63 private final NodeKey targetNodeKey;
65 public NodeStatisticsAger(StatisticsProvider statisticsProvider, NodeKey nodeKey){
66 this.statisticsProvider = Preconditions.checkNotNull(statisticsProvider);
67 this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
70 public class FlowEntry {
71 private final Short tableId;
72 private final Flow flow;
74 public FlowEntry(Short tableId, Flow flow){
75 this.tableId = tableId;
79 public Short getTableId() {
83 public Flow getFlow() {
88 public int hashCode() {
91 result = prime * result + getOuterType().hashCode();
92 result = prime * result + ((flow == null) ? 0 : flow.hashCode());
93 result = prime * result + ((tableId == null) ? 0 : tableId.hashCode());
98 public boolean equals(Object obj) {
103 if (getClass() != obj.getClass())
105 FlowEntry other = (FlowEntry) obj;
106 if (!getOuterType().equals(other.getOuterType()))
109 if (other.flow != null)
111 } else if (!flow.equals(other.flow))
113 if (tableId == null) {
114 if (other.tableId != null)
116 } else if (!tableId.equals(other.tableId))
121 private NodeStatisticsAger getOuterType() {
122 return NodeStatisticsAger.this;
126 public class QueueEntry{
127 private final NodeConnectorId nodeConnectorId;
128 private final QueueId queueId;
129 public QueueEntry(NodeConnectorId ncId, QueueId queueId){
130 this.nodeConnectorId = ncId;
131 this.queueId = queueId;
133 public NodeConnectorId getNodeConnectorId() {
134 return nodeConnectorId;
136 public QueueId getQueueId() {
140 public int hashCode() {
141 final int prime = 31;
143 result = prime * result + getOuterType().hashCode();
144 result = prime * result + ((nodeConnectorId == null) ? 0 : nodeConnectorId.hashCode());
145 result = prime * result + ((queueId == null) ? 0 : queueId.hashCode());
149 public boolean equals(Object obj) {
156 if (!(obj instanceof QueueEntry)) {
159 QueueEntry other = (QueueEntry) obj;
160 if (!getOuterType().equals(other.getOuterType())) {
163 if (nodeConnectorId == null) {
164 if (other.nodeConnectorId != null) {
167 } else if (!nodeConnectorId.equals(other.nodeConnectorId)) {
170 if (queueId == null) {
171 if (other.queueId != null) {
174 } else if (!queueId.equals(other.queueId)) {
179 private NodeStatisticsAger getOuterType() {
180 return NodeStatisticsAger.this;
184 public NodeKey getTargetNodeKey() {
185 return targetNodeKey;
188 public synchronized void updateGroupDescStats(List<GroupDescStats> list){
189 Long expiryTime = getExpiryTime();
190 for(GroupDescStats groupDescStats : list)
191 this.groupDescStatsUpdate.put(groupDescStats, expiryTime);
194 public synchronized void updateMeterConfigStats(List<MeterConfigStats> list){
195 Long expiryTime = getExpiryTime();
196 for(MeterConfigStats meterConfigStats: list)
197 this.meterConfigStatsUpdate.put(meterConfigStats, expiryTime);
200 public synchronized void updateFlowStats(FlowEntry flowEntry){
201 this.flowStatsUpdate.put(flowEntry, getExpiryTime());
203 public synchronized void updateQueueStats(QueueEntry queueEntry){
204 this.queuesStatsUpdate.put(queueEntry, getExpiryTime());
207 private static Long getExpiryTime(){
208 final long now = System.nanoTime();
209 return now + TimeUnit.MILLISECONDS.toNanos(StatisticsProvider.STATS_THREAD_EXECUTION_TIME * NUMBER_OF_WAIT_CYCLES);
212 public synchronized void cleanStaleStatistics(){
213 final DataModificationTransaction trans = this.statisticsProvider.startChange();
214 final long now = System.nanoTime();
216 //Clean stale statistics related to group
217 for (Iterator<Entry<GroupDescStats, Long>> it = this.groupDescStatsUpdate.entrySet().iterator();it.hasNext();){
218 Entry<GroupDescStats, Long> e = it.next();
219 if (now > e.getValue()) {
220 cleanGroupStatsFromDataStore(trans, e.getKey());
225 //Clean stale statistics related to meter
226 for (Iterator<Entry<MeterConfigStats, Long>> it = this.meterConfigStatsUpdate.entrySet().iterator();it.hasNext();){
227 Entry<MeterConfigStats, Long> e = it.next();
228 if (now > e.getValue()) {
229 cleanMeterStatsFromDataStore(trans, e.getKey());
234 //Clean stale statistics related to flow
235 for (Iterator<Entry<FlowEntry, Long>> it = this.flowStatsUpdate.entrySet().iterator();it.hasNext();){
236 Entry<FlowEntry, Long> e = it.next();
237 if (now > e.getValue()) {
238 cleanFlowStatsFromDataStore(trans, e.getKey());
243 //Clean stale statistics related to queue
244 for (Iterator<Entry<QueueEntry, Long>> it = this.queuesStatsUpdate.entrySet().iterator();it.hasNext();){
245 Entry<QueueEntry, Long> e = it.next();
246 if (now > e.getValue()) {
247 cleanQueueStatsFromDataStore(trans, e.getKey());
255 private void cleanQueueStatsFromDataStore(DataModificationTransaction trans, QueueEntry queueEntry) {
256 InstanceIdentifier<?> queueRef
257 = InstanceIdentifier.builder(Nodes.class)
258 .child(Node.class, this.targetNodeKey)
259 .child(NodeConnector.class, new NodeConnectorKey(queueEntry.getNodeConnectorId()))
260 .augmentation(FlowCapableNodeConnector.class)
261 .child(Queue.class, new QueueKey(queueEntry.getQueueId()))
262 .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).toInstance();
263 trans.removeOperationalData(queueRef);
266 private void cleanFlowStatsFromDataStore(DataModificationTransaction trans, FlowEntry flowEntry) {
267 InstanceIdentifier<?> flowRef
268 = InstanceIdentifier.builder(Nodes.class).child(Node.class, this.targetNodeKey)
269 .augmentation(FlowCapableNode.class)
270 .child(Table.class, new TableKey(flowEntry.getTableId()))
271 .child(Flow.class,flowEntry.getFlow().getKey())
272 .augmentation(FlowStatisticsData.class).toInstance();
273 trans.removeOperationalData(flowRef);
276 private void cleanMeterStatsFromDataStore(DataModificationTransaction trans, MeterConfigStats meterConfigStats) {
277 InstanceIdentifierBuilder<Meter> meterRef
278 = InstanceIdentifier.builder(Nodes.class).child(Node.class,this.targetNodeKey)
279 .augmentation(FlowCapableNode.class)
280 .child(Meter.class,new MeterKey(meterConfigStats.getMeterId()));
282 InstanceIdentifier<?> nodeMeterConfigStatsAugmentation = meterRef.augmentation(NodeMeterConfigStats.class).toInstance();
283 trans.removeOperationalData(nodeMeterConfigStatsAugmentation);
285 InstanceIdentifier<?> nodeMeterStatisticsAugmentation = meterRef.augmentation(NodeMeterStatistics.class).toInstance();
286 trans.removeOperationalData(nodeMeterStatisticsAugmentation);
289 private void cleanGroupStatsFromDataStore(DataModificationTransaction trans, GroupDescStats groupDescStats) {
290 InstanceIdentifierBuilder<Group> groupRef
291 = InstanceIdentifier.builder(Nodes.class).child(Node.class,this.targetNodeKey)
292 .augmentation(FlowCapableNode.class)
293 .child(Group.class,new GroupKey(groupDescStats.getGroupId()));
295 InstanceIdentifier<?> nodeGroupDescStatsAugmentation = groupRef.augmentation(NodeGroupDescStats.class).toInstance();
296 trans.removeOperationalData(nodeGroupDescStatsAugmentation);
298 InstanceIdentifier<?> nodeGroupStatisticsAugmentation = groupRef.augmentation(NodeGroupStatistics.class).toInstance();
299 trans.removeOperationalData(nodeGroupStatisticsAugmentation);