/** * Copyright (c) 2013 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.openflow.md.queue; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * message counter (by type) */ public class MessageSpyCounterImpl implements MessageObservatory { private static final Logger LOG = LoggerFactory .getLogger(MessageSpyCounterImpl.class); private static final class MessageCounters { private static final AtomicLongFieldUpdater UPDATER = AtomicLongFieldUpdater.newUpdater(MessageCounters.class, "current"); private volatile long current; private long cumulative; public synchronized long accumulate() { final long inc = UPDATER.getAndSet(this, 0); cumulative += inc; return inc; } public synchronized long getCumulative() { return cumulative; } public long increment() { return UPDATER.incrementAndGet(this); } } private final ConcurrentMap, MessageCounters>> inputStats = new ConcurrentHashMap<>(); @Override public void spyIn(final DataContainer message) { getCounters(message, STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_IN_SUCCESS).increment(); } @Override public void spyOut(final DataContainer message) { getCounters(message, STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_OUT_SUCCESS).increment(); } @Override public void spyMessage(final DataContainer message, final STATISTIC_GROUP statGroup) { getCounters(message, statGroup).increment(); } /** * @param message * @param statGroup TODO * @return */ private MessageCounters getCounters(final DataContainer message, final STATISTIC_GROUP statGroup) { Class msgType = message.getImplementedInterface(); ConcurrentMap, MessageCounters> groupData = getOrCreateGroupData(statGroup); MessageCounters counters = getOrCreateCountersPair(msgType, groupData); return counters; } private static MessageCounters getOrCreateCountersPair(final Class msgType, final ConcurrentMap,MessageCounters> groupData) { final MessageCounters lookup = groupData.get(msgType); if (lookup != null) { return lookup; } final MessageCounters newCounters = new MessageCounters(); final MessageCounters check = groupData.putIfAbsent(msgType, newCounters); return check == null ? newCounters : check; } private ConcurrentMap, MessageCounters> getOrCreateGroupData(final STATISTIC_GROUP statGroup) { final ConcurrentMap, MessageCounters> lookup = inputStats.get(statGroup); if (lookup != null) { return lookup; } final ConcurrentMap, MessageCounters> newmap = new ConcurrentHashMap<>(); final ConcurrentMap, MessageCounters> check = inputStats.putIfAbsent(statGroup, newmap); return check == null ? newmap : check; } @Override public void run() { // log current counters and cleans it if (LOG.isDebugEnabled()) { for (String counterItem : dumpMessageCounts()) { LOG.debug(counterItem); } } } @Override public List dumpMessageCounts() { List dump = new ArrayList<>(); for (STATISTIC_GROUP statGroup : STATISTIC_GROUP.values()) { Map, MessageCounters> groupData = inputStats.get(statGroup); if (groupData != null) { for (Entry, MessageCounters> statEntry : groupData.entrySet()) { long amountPerInterval = statEntry.getValue().accumulate(); long cumulativeAmount = statEntry.getValue().getCumulative(); dump.add(String.format("%s: MSG[%s] -> +%d | %d", statGroup, statEntry.getKey().getSimpleName(), amountPerInterval, cumulativeAmount)); } } else { dump.add(String.format("%s: no activity detected", statGroup)); } } return dump; } }