/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.impl.statistics.ofpspecific; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier; /** * Created by Martin Bobak <mbobak@cisco.com> on 28.5.2015. */ public final class EventsTimeCounter { private static final Map<String, Map<String, EventTimeCounter>> DEVICES_EVENTS = new HashMap<>(); private EventsTimeCounter() { // Hiding implicit constructor } public static void markStart(final EventIdentifier eventIdentifier) { Map<String, EventTimeCounter> deviceEvents = getOrCreateCountersForDevice(eventIdentifier.getDeviceId()); EventTimeCounter eventTimeCounter = getOrCreateEventOfType(eventIdentifier.getEventName(), deviceEvents); eventTimeCounter.markStart(); } public static void markEnd(final EventIdentifier eventIdentifier) { Map<String, EventTimeCounter> deviceEvents = getOrCreateCountersForDevice(eventIdentifier.getDeviceId()); EventTimeCounter eventTimeCounter = getOrCreateEventOfType(eventIdentifier.getEventName(), deviceEvents); eventTimeCounter.markEnd(); } private static EventTimeCounter getOrCreateEventOfType(final String event, final Map<String, EventTimeCounter> deviceEvents) { EventTimeCounter lookup = deviceEvents.get(event); if (null == lookup) { lookup = new EventTimeCounter(); deviceEvents.put(event, lookup); } return lookup; } private static Map<String, EventTimeCounter> getOrCreateCountersForDevice(final String deviceId) { Map<String, EventTimeCounter> lookup = DEVICES_EVENTS.get(deviceId); if (null == lookup) { lookup = new HashMap<>(); DEVICES_EVENTS.put(deviceId, lookup); } return lookup; } public static List<String> provideTimes() { List<String> dump = new ArrayList<>(); for (Map.Entry<String, Map<String, EventTimeCounter>> deviceEntry : DEVICES_EVENTS.entrySet()) { Map<String, EventTimeCounter> eventsMap = deviceEntry.getValue(); dump.add("================================================"); dump.add(String.format("DEVICE : %s", deviceEntry.getKey())); for (Map.Entry<String, EventTimeCounter> eventEntry : eventsMap.entrySet()) { final String eventName = eventEntry.getKey(); final EventTimeCounter eventTimeCounter = eventEntry.getValue(); dump.add(String.format("%s", eventName)); dump.add(String.format(" MIN TIME (ms): %d", TimeUnit.MILLISECONDS.convert(eventTimeCounter.getMinimum(), TimeUnit.NANOSECONDS))); dump.add(String.format(" MAX TIME (ms): %d", TimeUnit.MILLISECONDS.convert(eventTimeCounter.getMaximum(), TimeUnit.NANOSECONDS))); dump.add(String.format(" AVG TIME (ms): %d", TimeUnit.MILLISECONDS.convert(eventTimeCounter.getAverage(), TimeUnit.NANOSECONDS))); } } return dump; } public static void resetAllCounters() { DEVICES_EVENTS.clear(); } private static final class EventTimeCounter { private volatile long delta = 0; private volatile long average = 0; private volatile long minimum = 0; private volatile long maximum = 0; private volatile long summary = 0; private volatile int counter = 0; public synchronized void markStart() { delta = System.nanoTime(); } public synchronized void markEnd() { if (0 == delta) { return; } counter++; delta = System.nanoTime() - delta; if (delta < minimum || minimum == 0) { minimum = delta; } if (delta > maximum) { maximum = delta; } if (average > 0 && delta > (average * 1.8)) { summary += average; } else { summary += delta; } average = summary / counter; } public synchronized void resetCounters() { delta = 0; average = 0; minimum = 0; maximum = 0; summary = 0; counter = 0; } public synchronized long getAverage() { return average; } public synchronized long getMinimum() { return minimum; } public synchronized long getMaximum() { return maximum; } } }