X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-clustering-commons%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fcommon%2Factor%2FMessageTracker.java;h=1ba5ac6bdeb485a53fee0948df88b824a4b32ba6;hp=08516252fd601608f661f44293efe105de914033;hb=HEAD;hpb=2e75f2a8df84ff50d2b608c3346978d81378ee98 diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/MessageTracker.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/MessageTracker.java index 08516252fd..1ba5ac6bde 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/MessageTracker.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/MessageTracker.java @@ -5,21 +5,22 @@ * 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.controller.cluster.common.actor; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; + import com.google.common.annotations.Beta; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import com.google.common.base.Ticker; import com.google.common.collect.ImmutableList; import java.util.LinkedList; import java.util.List; -import javax.annotation.concurrent.NotThreadSafe; +import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +29,7 @@ import org.slf4j.LoggerFactory; * expected to arrive in a given time interval does not arrive. It attempts to keep track of all the messages that * received between the arrival of two instances of the same message and the amount of time it took to process each * of those messages. - *
+ *
* Usage of the API is as follows, *
  *
@@ -41,34 +42,39 @@ import org.slf4j.LoggerFactory;
  *
  *     .....
  *
- *     MessageTracker.Context context = tracker.received(message);
- *
- *     if(context.error().isPresent()){
- *         LOG.error("{}", context.error().get());
- *     }
+ *     try (MessageTracker.Context context = tracker.received(message)) {
  *
- *     // Some custom processing
- *     process(message);
+ *         if (context.error().isPresent()){
+ *             LOG.error("{}", context.error().get());
+ *         }
  *
- *     context.done();
+ *         // Some custom processing
+ *         process(message);
+ *     }
  *
  * 
+ * + *

+ * This class is NOT thread-safe. */ @Beta -@NotThreadSafe public final class MessageTracker { - public static abstract class Context { + public abstract static class Context implements AutoCloseable { Context() { // Hidden to prevent outside instantiation } - public abstract Context done(); public abstract Optional error(); + + @Override + public abstract void close(); } public interface Error { Object getLastExpectedMessage(); + Object getCurrentExpectedMessage(); + List getMessageProcessingTimesSinceLastExpectedMessage(); } @@ -78,18 +84,17 @@ public final class MessageTracker { private final long elapsedTimeInNanos; MessageProcessingTime(final Class messageClass, final long elapsedTimeInNanos) { - this.messageClass = Preconditions.checkNotNull(messageClass); + this.messageClass = requireNonNull(messageClass); this.elapsedTimeInNanos = elapsedTimeInNanos; } @Override public String toString() { - return "MessageProcessingTime{" + - "messageClass=" + messageClass.getSimpleName() + - ", elapsedTimeInMillis=" + NANOSECONDS.toMillis(elapsedTimeInNanos) + - '}'; + return "MessageProcessingTime [messageClass=" + messageClass + ", elapsedTimeInMillis=" + + NANOSECONDS.toMillis(elapsedTimeInNanos) + "]"; } + public Class getMessageClass() { return messageClass; } @@ -102,13 +107,13 @@ public final class MessageTracker { private static final Logger LOG = LoggerFactory.getLogger(MessageTracker.class); private static final Context NO_OP_CONTEXT = new Context() { @Override - public Context done() { - return this; + public void close() { + // No-op } @Override public Optional error() { - return Optional.absent(); + return Optional.empty(); } }; @@ -129,18 +134,19 @@ public final class MessageTracker { @VisibleForTesting MessageTracker(final Class expectedMessageClass, final long expectedArrivalIntervalInMillis, final Ticker ticker) { - Preconditions.checkArgument(expectedArrivalIntervalInMillis >= 0); - this.expectedMessageClass = Preconditions.checkNotNull(expectedMessageClass); + checkArgument(expectedArrivalIntervalInMillis >= 0); + this.expectedMessageClass = requireNonNull(expectedMessageClass); this.expectedArrivalInterval = MILLISECONDS.toNanos(expectedArrivalIntervalInMillis); - this.ticker = Preconditions.checkNotNull(ticker); + this.ticker = requireNonNull(ticker); this.expectedMessageWatch = Stopwatch.createUnstarted(ticker); this.currentMessageContext = new CurrentMessageContext(); } /** + * Constructs an instance. * - * @param expectedMessageClass The class of the message to track - * @param expectedArrivalIntervalInMillis The expected arrival interval between two instances of the expected + * @param expectedMessageClass the class of the message to track + * @param expectedArrivalIntervalInMillis the expected arrival interval between two instances of the expected * message */ public MessageTracker(final Class expectedMessageClass, final long expectedArrivalIntervalInMillis) { @@ -219,11 +225,11 @@ public final class MessageTracker { @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("\n> Last Expected Message = ").append(lastExpectedMessage); - builder.append("\n> Current Expected Message = ").append(currentExpectedMessage); - builder.append("\n> Expected time in between messages = ").append(expectedTimeInMillis); - builder.append("\n> Actual time in between messages = ").append(actualTimeInMillis); + StringBuilder builder = new StringBuilder() + .append("\n> Last Expected Message = ").append(lastExpectedMessage) + .append("\n> Current Expected Message = ").append(currentExpectedMessage) + .append("\n> Expected time in between messages = ").append(expectedTimeInMillis) + .append("\n> Actual time in between messages = ").append(actualTimeInMillis); for (MessageProcessingTime time : messagesSinceLastExpectedMessage) { builder.append("\n\t> ").append(time); } @@ -233,12 +239,12 @@ public final class MessageTracker { private abstract class AbstractTimedContext extends Context { abstract Object message(); + abstract Stopwatch stopTimer(); @Override - public final Context done() { + public final void close() { processed(message(), stopTimer().elapsed(NANOSECONDS)); - return this; } } @@ -246,10 +252,10 @@ public final class MessageTracker { private final Stopwatch stopwatch = Stopwatch.createUnstarted(ticker); private Object message; - void reset(final Object message) { - this.message = Preconditions.checkNotNull(message); - Preconditions.checkState(!stopwatch.isRunning(), - "Trying to reset a context that is not done (%s). currentMessage = %s", this, message); + void reset(final Object newMessage) { + this.message = requireNonNull(newMessage); + checkState(!stopwatch.isRunning(), "Trying to reset a context that is not done (%s). currentMessage = %s", + this, newMessage); stopwatch.start(); } @@ -265,7 +271,7 @@ public final class MessageTracker { @Override public Optional error() { - return Optional.absent(); + return Optional.empty(); } } @@ -275,8 +281,8 @@ public final class MessageTracker { private final Error error; ErrorContext(final Object message, final Error error) { - this.message = Preconditions.checkNotNull(message); - this.error = Preconditions.checkNotNull(error); + this.message = requireNonNull(message); + this.error = requireNonNull(error); } @Override