Bug 3435 - add time counter for selected operations on device 32/21632/1
authorMartin Bobak <mbobak@cisco.com>
Thu, 28 May 2015 16:23:28 +0000 (18:23 +0200)
committermichal rehak <mirehak@cisco.com>
Tue, 2 Jun 2015 10:05:13 +0000 (10:05 +0000)
Change-Id: Ie96860f8a253b57b82a8fb7e9577a8774b09a31f
Signed-off-by: Martin Bobak <mbobak@cisco.com>
(cherry picked from commit 667dd701f243e6344e864615559bbeb93d80bae8)

13 files changed:
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/handlers/MultiMsgCollector.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/ofpspecific/EventIdentifier.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/listener/MultiMsgCollectorImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ResetEventTimesComandProvider.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ShowEventTimesComandProvider.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractRequestCallback.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestCallback.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtils.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/ofpspecific/EventsTimeCounter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/dedicated/StatisticsGatheringService.java
openflowplugin-impl/src/main/resources/OSGI-INF/blueprint/commands.xml

index 2267d736fc5b711c334f86417bec2e3a3205adb6..6d597eb931a184e6db0bc20c7338f36f12e552de 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.openflowplugin.api.openflow.device.handlers;
 
 import javax.annotation.Nonnull;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 
 /**
@@ -32,10 +33,15 @@ public interface MultiMsgCollector {
      */
     void addMultipartMsg(@Nonnull MultipartReply reply);
 
+    void addMultipartMsg(@Nonnull MultipartReply reply, @Nonnull EventIdentifier eventIdentifier);
+
     /**
      * Null response could be a valid end multipart collecting event for barrier response scenario.
      * We are not able to resolve an issue (it is or it isn't barrier scenario) so we have to finish
      * collecting multipart messages successfully.
      */
     void endCollecting();
+
+    void endCollecting(EventIdentifier eventIdentifier);
+
 }
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/ofpspecific/EventIdentifier.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/ofpspecific/EventIdentifier.java
new file mode 100644 (file)
index 0000000..daba978
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.api.openflow.statistics.ofpspecific;
+
+/**
+ * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 29.5.2015.
+ */
+public final class EventIdentifier {
+
+    private final String eventName;
+    private final String deviceId;
+
+    public EventIdentifier(final String eventName, final String deviceId) {
+        this.eventName = eventName;
+        this.deviceId = deviceId;
+    }
+
+    public String getEventName() {
+        return eventName;
+    }
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+}
index ffb44d2ee8949ccef0ed25419061f6246709f52d..b373427f59812140844072567529421e78bcbd63 100644 (file)
@@ -11,12 +11,13 @@ package org.opendaylight.openflowplugin.impl.device.listener;
 import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.List;
+import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceReplyProcessor;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
@@ -26,7 +27,6 @@ import org.slf4j.LoggerFactory;
 
 /**
  * <p>
  * Implementation for {@link MultiMsgCollector} interface
  *
  * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
@@ -50,6 +50,11 @@ public class MultiMsgCollectorImpl implements MultiMsgCollector {
 
     @Override
     public void addMultipartMsg(final MultipartReply reply) {
+        addMultipartMsg(reply, null);
+    }
+
+    @Override
+    public void addMultipartMsg(@Nonnull final MultipartReply reply, @Nonnull final EventIdentifier eventIdentifier) {
         Preconditions.checkNotNull(reply);
         Preconditions.checkArgument(requestContext.getXid().getValue().equals(reply.getXid()));
         LOG.trace("Try to add Multipart reply msg with XID {}", reply.getXid());
@@ -64,12 +69,19 @@ public class MultiMsgCollectorImpl implements MultiMsgCollector {
 
         replyCollection.add(reply);
         if (!reply.getFlags().isOFPMPFREQMORE()) {
-            endCollecting();
+            endCollecting(eventIdentifier);
         }
     }
 
     public void endCollecting() {
+        endCollecting(null);
+    }
+
+    public void endCollecting(final EventIdentifier eventIdentifier) {
         final RpcResult<List<MultipartReply>> rpcResult = RpcResultBuilder.success(replyCollection).build();
+        if (null != eventIdentifier) {
+            EventsTimeCounter.markEnd(eventIdentifier);
+        }
         requestContext.setResult(rpcResult);
         requestContext.close();
         deviceReplyProcessor.processReply(requestContext.getXid(), replyCollection);
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ResetEventTimesComandProvider.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ResetEventTimesComandProvider.java
new file mode 100644 (file)
index 0000000..cf093f3
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.karaf;
+
+import java.io.PrintStream;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
+
+/**
+ * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 28.5.2015.
+ */
+@Command(scope = "ofp", name = "reset-time-counters", description = "Resets events time counters.")
+public class ResetEventTimesComandProvider extends OsgiCommandSupport {
+
+    @Override
+    protected Object doExecute() throws Exception {
+        PrintStream out = session.getConsole();
+        EventsTimeCounter.resetAllCounters();
+        out.print("Events time counters reset.\n");
+        return null;
+    }
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ShowEventTimesComandProvider.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ShowEventTimesComandProvider.java
new file mode 100644 (file)
index 0000000..751a6e5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.karaf;
+
+import java.io.PrintStream;
+import java.util.List;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
+
+/**
+ * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 28.5.2015.
+ */
+@Command(scope = "ofp", name = "show-time-counters", description = "Shows time counts for events.")
+public class ShowEventTimesComandProvider extends OsgiCommandSupport {
+
+    @Override
+    protected Object doExecute() throws Exception {
+        PrintStream out = session.getConsole();
+        final List<String> statistics = EventsTimeCounter.provideTimes();
+        final StringBuilder result = new StringBuilder();
+        for (String line : statistics) {
+            result.append(line);
+            result.append("\n");
+        }
+        out.print(result.toString());
+        return null;
+    }
+}
index 2881d6dcc397cf42332c2c3b9dda185dbc5d5594..f2949cef162ac4cd505401b744e752902d36120c 100644 (file)
@@ -22,6 +22,8 @@ public abstract class AbstractMultipartService<I> extends AbstractService<I, Lis
 
     @Override
     protected final FutureCallback<OfHeader> createCallback(final RequestContext<List<MultipartReply>> context, final Class<?> requestType) {
-        return new MultipartRequestCallback(context, requestType, getDeviceContext());
+        return new MultipartRequestCallback(context, requestType, getDeviceContext(), getEventIdentifier());
     }
+
+
 }
index 47692c7956af6dd2934c99dea2b33d2fa884d222..95c0071e750c7fa374a0aa8f5f245cf523502086 100644 (file)
@@ -13,8 +13,10 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.openflowjava.protocol.api.connection.DeviceRequestFailedException;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy.STATISTIC_GROUP;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.common.RpcError;
@@ -25,6 +27,8 @@ abstract class AbstractRequestCallback<T> implements FutureCallback<OfHeader> {
     private final RequestContext<T> context;
     private final Class<?> requestType;
     private final MessageSpy spy;
+    private EventIdentifier eventIdentifier;
+
 
     protected AbstractRequestCallback(final RequestContext<T> context, final Class<?> requestType, final MessageSpy spy) {
         this.context = Preconditions.checkNotNull(context);
@@ -32,6 +36,16 @@ abstract class AbstractRequestCallback<T> implements FutureCallback<OfHeader> {
         this.spy = Preconditions.checkNotNull(spy);
     }
 
+    protected AbstractRequestCallback(final RequestContext<T> context,
+                                      final Class<?> requestType,
+                                      final MessageSpy spy,
+                                      final EventIdentifier eventIdentifier) {
+        this.context = Preconditions.checkNotNull(context);
+        this.requestType = Preconditions.checkNotNull(requestType);
+        this.spy = Preconditions.checkNotNull(spy);
+        this.eventIdentifier = eventIdentifier;
+    }
+
     protected final void setResult(@Nullable final RpcResult<T> result) {
         context.setResult(result);
         context.close();
@@ -41,9 +55,16 @@ abstract class AbstractRequestCallback<T> implements FutureCallback<OfHeader> {
         spy.spyMessage(requestType, Preconditions.checkNotNull(group));
     }
 
+    public EventIdentifier getEventIdentifier() {
+        return eventIdentifier;
+    }
+
     @Override
     public final void onFailure(final Throwable t) {
         final RpcResultBuilder<T> builder;
+        if (null != eventIdentifier) {
+            EventsTimeCounter.markEnd(eventIdentifier);
+        }
         if (t instanceof DeviceRequestFailedException) {
             final Error err = ((DeviceRequestFailedException) t).getError();
             final String errorString = String.format("Device reported error type %s code %s", err.getTypeString(), err.getCodeString());
index 075271017e524b03eed72dbf9aa4a7532c15d7be..927f8d557b6ddc024879d7d151199e75e139c68d 100644 (file)
@@ -16,11 +16,11 @@ import java.math.BigInteger;
 import javax.annotation.Nonnull;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
@@ -42,6 +42,7 @@ abstract class AbstractService<I, O> {
     private final DeviceContext deviceContext;
     private final ConnectionAdapter primaryConnectionAdapter;
     private final MessageSpy messageSpy;
+    private EventIdentifier eventIdentifier;
 
     public AbstractService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
         this.requestContextStack = requestContextStack;
@@ -53,6 +54,14 @@ abstract class AbstractService<I, O> {
         this.messageSpy = deviceContext.getMessageSpy();
     }
 
+    public EventIdentifier getEventIdentifier() {
+        return eventIdentifier;
+    }
+
+    public void setEventIdentifier(final EventIdentifier eventIdentifier) {
+        this.eventIdentifier = eventIdentifier;
+    }
+
     public short getVersion() {
         return version;
     }
@@ -74,6 +83,7 @@ abstract class AbstractService<I, O> {
     }
 
     protected abstract OfHeader buildRequest(Xid xid, I input);
+
     protected abstract FutureCallback<OfHeader> createCallback(RequestContext<O> context, Class<?> requestType);
 
     public final ListenableFuture<RpcResult<O>> handleServiceCall(@Nonnull final I input) {
index 56a12a4248921556a0881db53dc371264ba41825..27369a36164040e5998a040361a3b7af863a1f49 100644 (file)
@@ -11,6 +11,7 @@ import java.util.List;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.common.RpcError;
@@ -27,11 +28,19 @@ final class MultipartRequestCallback extends AbstractRequestCallback<List<Multip
         collector = deviceContext.getMultiMsgCollector(context);
     }
 
+    public MultipartRequestCallback(final RequestContext<List<MultipartReply>> context,
+                                    final Class<?> requestType,
+                                    final DeviceContext deviceContext,
+                                    final EventIdentifier eventIdentifier) {
+        super(context, requestType, deviceContext.getMessageSpy(), eventIdentifier);
+        collector = deviceContext.getMultiMsgCollector(context);
+    }
+
     @Override
     public void onSuccess(final OfHeader result) {
         if (result == null) {
             LOG.info("Ofheader was null.");
-            collector.endCollecting();
+            collector.endCollecting(getEventIdentifier());
             return;
         }
 
@@ -39,10 +48,10 @@ final class MultipartRequestCallback extends AbstractRequestCallback<List<Multip
             LOG.info("Unexpected response type received {}.", result.getClass());
             final RpcResultBuilder<List<MultipartReply>> rpcResultBuilder =
                     RpcResultBuilder.<List<MultipartReply>>failed().withError(RpcError.ErrorType.APPLICATION,
-                        String.format("Unexpected response type received %s.", result.getClass()));
+                            String.format("Unexpected response type received %s.", result.getClass()));
             setResult(rpcResultBuilder.build());
         } else {
-            collector.addMultipartMsg((MultipartReply) result);
+            collector.addMultipartMsg((MultipartReply) result, getEventIdentifier());
         }
     }
 
index d3eabd2b6eea0fb120c0ae642bef2aea2c703de2..97a9e7d319d25e71ec3c01ea03871b1001b0fe1c 100644 (file)
@@ -24,7 +24,9 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
@@ -101,24 +103,32 @@ public final class StatisticsGatheringUtils {
 
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsGatheringUtils.class);
     private static final SinglePurposeMultipartReplyTranslator MULTIPART_REPLY_TRANSLATOR = new SinglePurposeMultipartReplyTranslator();
+    public static final String QUEUE2_REQCTX = "QUEUE2REQCTX-";
 
     private StatisticsGatheringUtils() {
         throw new IllegalStateException("This class should not be instantiated.");
     }
 
 
-
     public static ListenableFuture<Boolean> gatherStatistics(final StatisticsGatheringService statisticsGatheringService,
                                                              final DeviceContext deviceContext,
                                                              final MultipartType type) {
         //FIXME : anytype listener must not be send as parameter, it has to be extracted from device context inside service
+        final String deviceId = deviceContext.getPrimaryConnectionContext().getNodeId().toString();
+        EventIdentifier wholeProcessEventIdentifier = null;
+        if (MultipartType.OFPMPFLOW.equals(type)) {
+            wholeProcessEventIdentifier = new EventIdentifier(type.toString(), deviceId);
+            EventsTimeCounter.markStart(wholeProcessEventIdentifier);
+        }
+        EventIdentifier ofpQueuToRequestContextEventIdentifier = new EventIdentifier(QUEUE2_REQCTX + type.toString(), deviceId);
         final ListenableFuture<RpcResult<List<MultipartReply>>> statisticsDataInFuture =
-                JdkFutureAdapters.listenInPoolThread(statisticsGatheringService.getStatisticsOfType(type));
-        return transformAndStoreStatisticsData(statisticsDataInFuture, deviceContext);
+                JdkFutureAdapters.listenInPoolThread(statisticsGatheringService.getStatisticsOfType(ofpQueuToRequestContextEventIdentifier, type));
+        return transformAndStoreStatisticsData(statisticsDataInFuture, deviceContext, wholeProcessEventIdentifier);
     }
 
     private static ListenableFuture<Boolean> transformAndStoreStatisticsData(final ListenableFuture<RpcResult<List<MultipartReply>>> statisticsDataInFuture,
-                                                                             final DeviceContext deviceContext) {
+                                                                             final DeviceContext deviceContext,
+                                                                             final EventIdentifier eventIdentifier) {
         return Futures.transform(statisticsDataInFuture, new Function<RpcResult<List<MultipartReply>>, Boolean>() {
             @Nullable
             @Override
@@ -145,6 +155,7 @@ public final class StatisticsGatheringUtils {
                         processQueueStatistics((Iterable<QueueStatisticsUpdate>) allMultipartData, deviceContext);
                     } else if (multipartData instanceof FlowsStatisticsUpdate) {
                         processFlowStatistics((Iterable<FlowsStatisticsUpdate>) allMultipartData, deviceContext);
+                        EventsTimeCounter.markEnd(eventIdentifier);
                     } else if (multipartData instanceof GroupDescStatsUpdated) {
                         processGroupDescStats((Iterable<GroupDescStatsUpdated>) allMultipartData, deviceContext);
                     } else if (multipartData instanceof MeterConfigStatsUpdated) {
@@ -205,9 +216,9 @@ public final class StatisticsGatheringUtils {
     private static void deleteAllKnownFlows(final DeviceContext deviceContext, final InstanceIdentifier<Node> nodeIdent) {
         if (deviceContext.getDeviceState().deviceSynchronized()) {
             final Short numOfTablesOnDevice = deviceContext.getDeviceState().getFeatures().getTables();
-            for (short i=0; i<numOfTablesOnDevice; i++) {
+            for (short i = 0; i < numOfTablesOnDevice; i++) {
                 final KeyedInstanceIdentifier<Table, TableKey> iiToTable
-                    = nodeIdent.augmentation(FlowCapableNode.class).child( Table.class, new TableKey(i));
+                        = nodeIdent.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(i));
                 final ReadTransaction readTx = deviceContext.getReadTransaction();
                 final CheckedFuture<Optional<Table>, ReadFailedException> tableDataFuture = readTx.read(LogicalDatastoreType.OPERATIONAL, iiToTable);
                 try {
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/ofpspecific/EventsTimeCounter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/ofpspecific/EventsTimeCounter.java
new file mode 100644 (file)
index 0000000..3ecbc0a
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * 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 &lt;mbobak@cisco.com&gt; on 28.5.2015.
+ */
+public final class EventsTimeCounter {
+
+    private static Map<String, Map<String, EventTimeCounter>> devicesEvents = new HashMap<>();
+
+    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 = devicesEvents.get(deviceId);
+        if (null == lookup) {
+            lookup = new HashMap<String, EventTimeCounter>();
+            devicesEvents.put(deviceId, lookup);
+        }
+
+        return lookup;
+    }
+
+    public static List<String> provideTimes() {
+        List<String> dump = new ArrayList<>();
+        for (Map.Entry<String, Map<String, EventTimeCounter>> deviceEntry : devicesEvents.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() {
+        devicesEvents = new HashMap<>();
+    }
+
+
+    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;
+            }
+            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;
+        }
+
+    }
+
+
+}
index deea2e4a749cfcde3b8910684761ba520ebbc31d..8c8358e9ffe7ee366d078639ef1f147dfa1d3fc1 100644 (file)
@@ -13,8 +13,10 @@ import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.impl.common.MultipartRequestInputFactory;
 import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
@@ -24,11 +26,14 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 4.4.2015.
  */
 public class StatisticsGatheringService extends AbstractMultipartService<MultipartType> {
+
     public StatisticsGatheringService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
         super(requestContextStack, deviceContext);
     }
 
-    public Future<RpcResult<List<MultipartReply>>> getStatisticsOfType(final MultipartType type) {
+    public Future<RpcResult<List<MultipartReply>>> getStatisticsOfType(final EventIdentifier eventIdentifier, final MultipartType type) {
+        EventsTimeCounter.markStart(eventIdentifier);
+        setEventIdentifier(eventIdentifier);
         return handleServiceCall(type);
     }
 
index 6397e6435de939d724168e31ce69522aa701f38d..ded2fbef37ee7eafabbfbaf282de4ca90c923904 100644 (file)
         <command name="ofp/clearStats">
             <action class="org.opendaylight.openflowplugin.impl.karaf.ClearStatsCommandProvider"/>
         </command>
+        <command name="ofp/show-time-counters">
+            <action class="org.opendaylight.openflowplugin.impl.karaf.ShowEventTimesComandProvider"/>
+        </command>
+        <command name="ofp/reset-time-counters">
+            <action class="org.opendaylight.openflowplugin.impl.karaf.ResetEventTimesComandProvider"/>
+        </command>
     </command-bundle>