unifying statistics manager api packages
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / statistics / MessageSpyCounterImpl.java
1 /**
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  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
9 package org.opendaylight.openflowplugin.statistics;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Map.Entry;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.ConcurrentMap;
17 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
18
19 import org.opendaylight.openflowplugin.api.openflow.statistics.MessageObservatory;
20 import org.opendaylight.yangtools.yang.binding.DataContainer;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * message counter (by type)
26  */
27 public class MessageSpyCounterImpl implements MessageObservatory<DataContainer> {
28
29     private static final Logger LOG = LoggerFactory.getLogger(MessageSpyCounterImpl.class);
30
31     private static final class MessageCounters {
32         private static final AtomicLongFieldUpdater<MessageCounters> UPDATER = AtomicLongFieldUpdater.newUpdater(MessageCounters.class, "current");
33         private volatile long current;
34         private long cumulative;
35
36         public synchronized long accumulate() {
37             final long inc = UPDATER.getAndSet(this, 0);
38             cumulative += inc;
39             return inc;
40         }
41
42         public synchronized long getCumulative() {
43             return cumulative;
44         }
45
46         public long increment() {
47             return UPDATER.incrementAndGet(this);
48         }
49     }
50
51     private final ConcurrentMap<STATISTIC_GROUP, ConcurrentMap<Class<? extends DataContainer>, MessageCounters>> inputStats = new ConcurrentHashMap<>();
52
53     @Override
54     public void spyIn(final DataContainer message) {
55         getCounters(message, STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_IN_SUCCESS).increment();
56     }
57
58     @Override
59     public void spyOut(final DataContainer message) {
60         getCounters(message, STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_OUT_SUCCESS).increment();
61     }
62
63     @Override
64     public void spyMessage(final DataContainer message, final STATISTIC_GROUP statGroup) {
65         getCounters(message, statGroup).increment();
66     }
67
68     /**
69      * @param message
70      * @param statGroup TODO
71      * @return
72      */
73     private MessageCounters getCounters(final DataContainer message, final STATISTIC_GROUP statGroup) {
74         Class<? extends DataContainer> msgType = message.getImplementedInterface();
75         ConcurrentMap<Class<? extends DataContainer>, MessageCounters> groupData = getOrCreateGroupData(statGroup);
76         MessageCounters counters = getOrCreateCountersPair(msgType, groupData);
77         return counters;
78     }
79
80     private static MessageCounters getOrCreateCountersPair(final Class<? extends DataContainer> msgType, final ConcurrentMap<Class<? extends DataContainer>,MessageCounters> groupData) {
81         final MessageCounters lookup = groupData.get(msgType);
82         if (lookup != null) {
83             return lookup;
84         }
85
86         final MessageCounters newCounters = new MessageCounters();
87         final MessageCounters check = groupData.putIfAbsent(msgType, newCounters);
88         return check == null ? newCounters : check;
89
90     }
91
92     private ConcurrentMap<Class<? extends DataContainer>, MessageCounters> getOrCreateGroupData(final STATISTIC_GROUP statGroup) {
93         final ConcurrentMap<Class<? extends DataContainer>, MessageCounters> lookup = inputStats.get(statGroup);
94         if (lookup != null) {
95             return lookup;
96         }
97
98         final ConcurrentMap<Class<? extends DataContainer>, MessageCounters> newmap = new ConcurrentHashMap<>();
99         final ConcurrentMap<Class<? extends DataContainer>, MessageCounters> check = inputStats.putIfAbsent(statGroup, newmap);
100
101         return check == null ? newmap : check;
102     }
103
104     @Override
105     public void run() {
106         // log current counters and cleans it
107         if (LOG.isDebugEnabled()) {
108             for (String counterItem : dumpMessageCounts()) {
109                 LOG.debug(counterItem);
110             }
111         }
112     }
113
114     @Override
115     public List<String> dumpMessageCounts() {
116         List<String> dump = new ArrayList<>();
117
118         for (STATISTIC_GROUP statGroup : STATISTIC_GROUP.values()) {
119             Map<Class<? extends DataContainer>, MessageCounters> groupData = inputStats.get(statGroup);
120             if (groupData != null) {
121                 for (Entry<Class<? extends DataContainer>, MessageCounters> statEntry : groupData.entrySet()) {
122                     long amountPerInterval = statEntry.getValue().accumulate();
123                     long cumulativeAmount = statEntry.getValue().getCumulative();
124                     dump.add(String.format("%s: MSG[%s] -> +%d | %d",
125                             statGroup,
126                             statEntry.getKey().getSimpleName(),
127                             amountPerInterval, cumulativeAmount));
128                 }
129             } else {
130                 dump.add(String.format("%s: no activity detected", statGroup));
131             }
132         }
133         return dump;
134     }
135 }