2 * Copyright (c) 2015 Cisco Systems, Inc. and others. 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
9 package org.opendaylight.openflowplugin.impl.statistics.ofpspecific;
11 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
16 import java.util.concurrent.TimeUnit;
17 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
19 public final class EventsTimeCounter {
21 private static final Map<String, Map<String, EventTimeCounter>> DEVICES_EVENTS = new HashMap<>();
23 private EventsTimeCounter() {
24 // Hiding implicit constructor
27 public static void markStart(final EventIdentifier eventIdentifier) {
28 Map<String, EventTimeCounter> deviceEvents = getOrCreateCountersForDevice(eventIdentifier.getDeviceId());
29 EventTimeCounter eventTimeCounter = getOrCreateEventOfType(eventIdentifier.getEventName(), deviceEvents);
30 eventTimeCounter.markStart();
33 public static void markEnd(final EventIdentifier eventIdentifier) {
34 Map<String, EventTimeCounter> deviceEvents = getOrCreateCountersForDevice(eventIdentifier.getDeviceId());
35 EventTimeCounter eventTimeCounter = getOrCreateEventOfType(eventIdentifier.getEventName(), deviceEvents);
36 eventTimeCounter.markEnd();
39 private static EventTimeCounter getOrCreateEventOfType(final String event,
40 final Map<String, EventTimeCounter> deviceEvents) {
41 return deviceEvents.computeIfAbsent(event, k -> new EventTimeCounter());
44 private static Map<String, EventTimeCounter> getOrCreateCountersForDevice(final String deviceId) {
45 return DEVICES_EVENTS.computeIfAbsent(deviceId, k -> new HashMap<>());
48 public static List<String> provideTimes() {
49 List<String> dump = new ArrayList<>();
50 for (Map.Entry<String, Map<String, EventTimeCounter>> deviceEntry : DEVICES_EVENTS.entrySet()) {
51 Map<String, EventTimeCounter> eventsMap = deviceEntry.getValue();
52 dump.add("================================================");
53 dump.add(String.format("DEVICE : %s", deviceEntry.getKey()));
54 for (Map.Entry<String, EventTimeCounter> eventEntry : eventsMap.entrySet()) {
55 final String eventName = eventEntry.getKey();
56 final EventTimeCounter eventTimeCounter = eventEntry.getValue();
57 dump.add(String.format("%s", eventName));
58 dump.add(String.format(" MIN TIME (ms): %d",
59 TimeUnit.MILLISECONDS.convert(eventTimeCounter.getMinimum(), TimeUnit.NANOSECONDS)));
60 dump.add(String.format(" MAX TIME (ms): %d",
61 TimeUnit.MILLISECONDS.convert(eventTimeCounter.getMaximum(), TimeUnit.NANOSECONDS)));
62 dump.add(String.format(" AVG TIME (ms): %d",
63 TimeUnit.MILLISECONDS.convert(eventTimeCounter.getAverage(), TimeUnit.NANOSECONDS)));
70 public static void resetAllCounters() {
71 DEVICES_EVENTS.clear();
75 private static final class EventTimeCounter {
77 private volatile long delta = 0;
78 private volatile long average = 0;
79 private volatile long minimum = 0;
80 private volatile long maximum = 0;
81 private volatile long summary = 0;
82 private volatile int counter = 0;
84 public synchronized void markStart() {
85 delta = System.nanoTime();
88 @SuppressFBWarnings("VO_VOLATILE_INCREMENT") // counter++ is volatile, but this is synchronized, so OK
89 public synchronized void markEnd() {
94 delta = System.nanoTime() - delta;
96 if (delta < minimum || minimum == 0) {
99 if (delta > maximum) {
102 if (average > 0 && delta > average * 1.8) {
107 average = summary / counter;
110 public synchronized void resetCounters() {
120 public synchronized long getAverage() {
124 public synchronized long getMinimum() {
128 public synchronized long getMaximum() {