OPNFLWPLUG-1090: ConcurrentModificationException: null when connecting cbench switches
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / statistics / ofpspecific / SessionStatistics.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.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
17
18 public final class SessionStatistics {
19
20     private SessionStatistics() {
21     }
22
23     private static final Map<String, Map<ConnectionStatus, EventCounter>> SESSION_EVENTS = new ConcurrentHashMap<>();
24
25     public static void countEvent(final String sessionId, final ConnectionStatus connectionStatus) {
26         Map<ConnectionStatus, EventCounter> sessionsConnectionEvents = getConnectionEvents(sessionId);
27         EventCounter connectionEvent = getConnectionEvent(sessionsConnectionEvents, connectionStatus);
28         connectionEvent.increment();
29     }
30
31     private static EventCounter getConnectionEvent(final Map<ConnectionStatus, EventCounter> sessionsConnectionEvents,
32                                                    final ConnectionStatus connectionStatus) {
33         return sessionsConnectionEvents.computeIfAbsent(connectionStatus, k -> new EventCounter());
34     }
35
36     private static Map<ConnectionStatus, EventCounter> getConnectionEvents(final String sessionId) {
37         return SESSION_EVENTS.computeIfAbsent(sessionId, k -> new HashMap<>());
38     }
39
40
41     public static List<String> provideStatistics() {
42         List<String> dump = new ArrayList<>();
43         for (Map.Entry<String, Map<ConnectionStatus, EventCounter>> sessionEntries : SESSION_EVENTS.entrySet()) {
44             Map<ConnectionStatus, EventCounter> sessionEvents = sessionEntries.getValue();
45             dump.add(String.format("SESSION : %s", sessionEntries.getKey()));
46             for (Map.Entry<ConnectionStatus, EventCounter> sessionEvent : sessionEvents.entrySet()) {
47                 dump.add(String.format(" %s : %d", sessionEvent.getKey().toString(),
48                                                    sessionEvent.getValue().getCount()));
49             }
50         }
51         return dump;
52
53     }
54
55     public enum ConnectionStatus {
56         CONNECTION_CREATED, CONNECTION_DISCONNECTED_BY_DEVICE, CONNECTION_DISCONNECTED_BY_OFP
57     }
58
59     private static final class EventCounter {
60         private final AtomicLongFieldUpdater<EventCounter> updater =
61                 AtomicLongFieldUpdater.newUpdater(EventCounter.class, "count");
62         private volatile long count;
63
64         public long getCount() {
65             return count;
66         }
67
68         public void increment() {
69             count = updater.incrementAndGet(this);
70         }
71     }
72
73     public static void resetAllCounters() {
74         SESSION_EVENTS.clear();
75     }
76
77 }