--- /dev/null
+/*
+ * Copyright (c) 2016 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.controller.cluster.access.concepts;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * General error raised when the recipient of a {@link Request} determines that the request contains
+ * a {@link ClientIdentifier} which corresponds to an outdated generation.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class RetiredGenerationException extends RequestException {
+ private static final long serialVersionUID = 1L;
+
+ public RetiredGenerationException(final long newGeneration) {
+ super("Originating generation was superseded by " + Long.toUnsignedString(newGeneration));
+ }
+
+ @Override
+ public boolean isRetriable() {
+ return false;
+ }
+}
//
//
+ @Override
+ protected void haltClient(final Throwable cause) {
+ // FIXME: Add state flushing here once we have state
+ }
+
private void createLocalHistory(final CreateLocalHistoryCommand command) {
final CompletableFuture<ClientLocalHistory> future = command.future();
final LocalHistoryIdentifier historyId = new LocalHistoryIdentifier(getIdentifier(), nextHistoryId++);
} else if (command instanceof GetClientRequest) {
((GetClientRequest) command).getReplyTo().tell(new Status.Success(this), ActorRef.noSender());
} else if (SHUTDOWN.equals(command)) {
- // Add shutdown procedures here
+ // FIXME: Add shutdown procedures here
return null;
} else {
LOG.warn("{}: ignoring unhandled command {}", persistenceId(), command);
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
+import org.opendaylight.controller.cluster.access.concepts.RequestException;
+import org.opendaylight.controller.cluster.access.concepts.RequestFailure;
+import org.opendaylight.controller.cluster.access.concepts.RetiredGenerationException;
import org.opendaylight.yangtools.concepts.Identifiable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A behavior, which handles messages sent to a {@link AbstractClientActor}.
@Beta
public abstract class ClientActorBehavior extends RecoveredClientActorBehavior<ClientActorContext>
implements Identifiable<ClientIdentifier> {
+ private static final Logger LOG = LoggerFactory.getLogger(ClientActorBehavior.class);
+
protected ClientActorBehavior(final @Nonnull ClientActorContext context) {
super(context);
}
@Override
final ClientActorBehavior onReceiveCommand(final Object command) {
+ if (command instanceof RequestFailure) {
+ final RequestFailure<?, ?> failure = (RequestFailure<?, ?>) command;
+ final RequestException cause = failure.getCause();
+ if (cause instanceof RetiredGenerationException) {
+ LOG.error("{}: current generation {} has been superseded", persistenceId(), getIdentifier(), cause);
+ haltClient(cause);
+ return null;
+ }
+ }
+
// TODO: any client-common logic (such as validation and common dispatch) needs to go here
return onCommand(command);
}
return context().getIdentifier();
}
+ /**
+ * Halt And Catch Fire.
+ *
+ * Halt processing on this client. Implementations need to ensure they initiate state flush procedures. No attempt
+ * to use this instance should be made after this method returns. Any such use may result in undefined behavior.
+ *
+ * @param cause Failure cause
+ */
+ protected abstract void haltClient(@Nonnull Throwable cause);
+
/**
* Override this method to handle any command which is not handled by the base behavior.
*