858f554091cbcb911c8d11b72cfc1e85dd18ecf7
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / statistics / ofpspecific / MessageIntelligenceAgencyImpl.java
1 /*
2  * Copyright (c) 2015 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.impl.statistics.ofpspecific;
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 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /**
23  * Implementation of {@link org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency}.
24  * Class counts message of {@link org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy.STATISTIC_GROUP} type
25  * and provides info as debug log.
26  */
27 public class MessageIntelligenceAgencyImpl implements MessageIntelligenceAgency<Class>, MessageIntelligenceAgencyMXBean {
28
29     private static final Logger LOG = LoggerFactory.getLogger(MessageIntelligenceAgencyImpl.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, MessageCounters>> inputStats = new ConcurrentHashMap<>();
52
53     @Override
54     public void spyMessage(final Class message, final STATISTIC_GROUP statGroup) {
55         getCounters(message, statGroup).increment();
56     }
57
58     /**
59      * @param message
60      * @param statGroup TODO
61      * @return
62      */
63     private MessageCounters getCounters(final Class message, final STATISTIC_GROUP statGroup) {
64         ConcurrentMap<Class, MessageCounters> groupData = getOrCreateGroupData(statGroup);
65         MessageCounters counters = getOrCreateCountersPair(message, groupData);
66         return counters;
67     }
68
69     private static MessageCounters getOrCreateCountersPair(final Class msgType, final ConcurrentMap<Class, MessageCounters> groupData) {
70         final MessageCounters lookup = groupData.get(msgType);
71         if (lookup != null) {
72             return lookup;
73         }
74
75         final MessageCounters newCounters = new MessageCounters();
76         final MessageCounters check = groupData.putIfAbsent(msgType, newCounters);
77         return check == null ? newCounters : check;
78
79     }
80
81     private ConcurrentMap<Class, MessageCounters> getOrCreateGroupData(final STATISTIC_GROUP statGroup) {
82         final ConcurrentMap<Class, MessageCounters> lookup = inputStats.get(statGroup);
83         if (lookup != null) {
84             return lookup;
85         }
86
87         final ConcurrentMap<Class, MessageCounters> newmap = new ConcurrentHashMap<>();
88         final ConcurrentMap<Class, MessageCounters> check = inputStats.putIfAbsent(statGroup, newmap);
89
90         return check == null ? newmap : check;
91     }
92
93     @Override
94     public void run() {
95         // log current counters and cleans it
96         if (LOG.isDebugEnabled()) {
97             for (String counterItem : provideIntelligence()) {
98                 LOG.debug(counterItem);
99             }
100         }
101     }
102
103     @Override
104     public List<String> provideIntelligence() {
105         List<String> dump = new ArrayList<>();
106
107         for (STATISTIC_GROUP statGroup : STATISTIC_GROUP.values()) {
108             Map<Class, MessageCounters> groupData = inputStats.get(statGroup);
109             if (groupData != null) {
110                 for (Entry<Class, MessageCounters> statEntry : groupData.entrySet()) {
111                     long amountPerInterval = statEntry.getValue().accumulate();
112                     long cumulativeAmount = statEntry.getValue().getCumulative();
113                     dump.add(String.format("%s: MSG[%s] -> +%d | %d",
114                             statGroup,
115                             statEntry.getKey().getSimpleName(),
116                             amountPerInterval, cumulativeAmount));
117                 }
118             } else {
119                 dump.add(String.format("%s: no activity detected", statGroup));
120             }
121         }
122         return dump;
123     }
124 }