<type>pom</type>
<scope>import</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-artifacts</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-api</artifactId>
</dependency>
+
+ <!-- Needed for serialization of yang-data-api objects -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-clustering-commons</artifactId>
+ </dependency>
</dependencies>
<scm>
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Request to abort a local transaction. Since local transactions do not introduce state on the backend until they
+ * are ready, the purpose of this message is to inform the backend that a message identifier has been used. This is
+ * not important for single transactions, but is critical to ensure transaction ordering within local histories.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class AbortLocalTransactionRequest extends AbstractLocalTransactionRequest<AbortLocalTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+
+ public AbortLocalTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final @Nonnull ActorRef replyTo) {
+ this(identifier, sequence, 0, replyTo);
+ }
+
+ AbortLocalTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final long retry, final @Nonnull ActorRef replyTo) {
+ super(identifier, sequence, retry, replyTo);
+ }
+
+ private AbortLocalTransactionRequest(final @Nonnull AbortLocalTransactionRequest request, final long retry) {
+ super(request, retry);
+ }
+
+ @Override
+ protected AbortLocalTransactionRequest cloneAsRetry(final long retry) {
+ return new AbortLocalTransactionRequest(this, retry);
+ }
+}
\ No newline at end of file
--- /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.commands;
+
+import akka.actor.ActorRef;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.Request;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Abstract base class for {@link Request}s involving specific transactions local to a member node. These transactions
+ * take advantage of isolation provided by the DataTree, performing transaction modifications on the frontend.
+ *
+ * @author Robert Varga
+ *
+ * @param <T> Message type
+ */
+abstract class AbstractLocalTransactionRequest<T extends AbstractLocalTransactionRequest<T>> extends TransactionRequest<T> {
+ private static final long serialVersionUID = 1L;
+
+ AbstractLocalTransactionRequest(final TransactionIdentifier identifier, final long sequence, final long retry,
+ final ActorRef replyTo) {
+ super(identifier, sequence, retry, replyTo);
+ }
+
+ AbstractLocalTransactionRequest(final T request, final long retry) {
+ super(request, retry);
+ }
+
+ @Override
+ protected final AbstractTransactionRequestProxy<T> externalizableProxy(final ABIVersion version) {
+ throw new UnsupportedOperationException("Local transaction request should never be serialized");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected final T cloneAsVersion(final ABIVersion version) {
+ // These messages cannot be serialized, hence we this method is a no-op
+ return (T)this;
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * Abstract base class for {@link TransactionRequest}s accessing data as visible in the isolated context of a particular
+ * transaction. The path of the data being accessed is returned via {@link #getPath()}.
+ *
+ * This class is visible outside of this package for the purpose of allowing common instanceof checks
+ * and simplified codepaths.
+ *
+ * @author Robert Varga
+ *
+ * @param <T> Message type
+ */
+@Beta
+public abstract class AbstractReadTransactionRequest<T extends AbstractReadTransactionRequest<T>> extends TransactionRequest<T> {
+ private static final long serialVersionUID = 1L;
+ private final YangInstanceIdentifier path;
+
+ AbstractReadTransactionRequest(final TransactionIdentifier identifier, final long sequence, final long retry,
+ final ActorRef replyTo, final YangInstanceIdentifier path) {
+ super(identifier, sequence, retry, replyTo);
+ this.path = Preconditions.checkNotNull(path);
+ }
+
+ AbstractReadTransactionRequest(final T request, final ABIVersion version) {
+ super(request, version);
+ this.path = request.getPath();
+ }
+
+ AbstractReadTransactionRequest(final T request, final long retry) {
+ super(request, retry);
+ this.path = request.getPath();
+ }
+
+ public final @Nonnull YangInstanceIdentifier getPath() {
+ return path;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return super.addToStringAttributes(toStringHelper).add("path", path);
+ }
+
+ @Override
+ protected abstract AbstractReadTransactionRequestProxyV1<T> externalizableProxy(final ABIVersion version);
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputOutput;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * Abstract base class for serialization proxies associated with {@link AbstractReadTransactionRequest}s. It implements
+ * the initial (Boron) serialization format.
+ *
+ * @author Robert Varga
+ *
+ * @param <T> Message type
+ */
+abstract class AbstractReadTransactionRequestProxyV1<T extends AbstractReadTransactionRequest<T>> extends AbstractTransactionRequestProxy<T> {
+ private static final long serialVersionUID = 1L;
+ private YangInstanceIdentifier path;
+
+ AbstractReadTransactionRequestProxyV1() {
+ // For Externalizable
+ }
+
+ AbstractReadTransactionRequestProxyV1(final T request) {
+ super(request);
+ }
+
+ @Override
+ public final void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ try (NormalizedNodeDataOutput nnout = NormalizedNodeInputOutput.newDataOutput(out)) {
+ nnout.writeYangInstanceIdentifier(path);
+ }
+ }
+
+ @Override
+ public final void readExternal(final ObjectInput in) throws ClassNotFoundException, IOException {
+ super.readExternal(in);
+ path = NormalizedNodeInputOutput.newDataInput(in).readYangInstanceIdentifier();
+ }
+
+ @Override
+ protected final T createRequest(final TransactionIdentifier target, final long sequence, final long retry,
+ final ActorRef replyTo) {
+ return createReadRequest(target, sequence, retry, replyTo, path);
+ }
+
+ abstract T createReadRequest(TransactionIdentifier target, long sequence, long retry, ActorRef replyTo,
+ YangInstanceIdentifier path);
+}
--- /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.commands;
+
+import java.io.DataInput;
+import java.io.IOException;
+import org.opendaylight.controller.cluster.access.concepts.AbstractRequestProxy;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Abstract base class for serialization proxies associated with {@link TransactionRequest}s.
+ *
+ * @author Robert Varga
+ *
+ * @param <T> Message type
+ */
+abstract class AbstractTransactionRequestProxy<T extends TransactionRequest<T>> extends AbstractRequestProxy<TransactionIdentifier, T> {
+ private static final long serialVersionUID = 1L;
+
+ AbstractTransactionRequestProxy() {
+ // For Externalizable
+ }
+
+ AbstractTransactionRequestProxy(final T request) {
+ super(request);
+ }
+
+ @Override
+ protected final TransactionIdentifier readTarget(final DataInput in) throws IOException {
+ return TransactionIdentifier.readFrom(in);
+ }
+}
--- /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.commands;
+
+import java.io.DataInput;
+import java.io.IOException;
+import org.opendaylight.controller.cluster.access.concepts.AbstractSuccessProxy;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Abstract base class for serialization proxies associated with {@link TransactionSuccess}es.
+ *
+ * @author Robert Varga
+ *
+ * @param <T> Message type
+ */
+abstract class AbstractTransactionSuccessProxy<T extends TransactionSuccess<T>> extends AbstractSuccessProxy<TransactionIdentifier, T> {
+ private static final long serialVersionUID = 1L;
+
+ AbstractTransactionSuccessProxy() {
+ // For Externalizable
+ }
+
+ AbstractTransactionSuccessProxy(final T request) {
+ super(request);
+ }
+
+ @Override
+ protected final TransactionIdentifier readTarget(final DataInput in) throws IOException {
+ return TransactionIdentifier.readFrom(in);
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+
+/**
+ * Request to commit a local transaction. Since local transactions do not introduce state on the backend until they
+ * are ready, this message carries a complete set of modifications.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class CommitLocalTransactionRequest extends AbstractLocalTransactionRequest<CommitLocalTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+ private final DataTreeModification mod;
+ private final boolean coordinated;
+
+ public CommitLocalTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final @Nonnull ActorRef replyTo, final @Nonnull DataTreeModification mod, final boolean coordinated) {
+ this(identifier, sequence, 0, replyTo, mod, coordinated);
+ }
+
+ CommitLocalTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final long retry, final @Nonnull ActorRef replyTo, final @Nonnull DataTreeModification mod,
+ final boolean coordinated) {
+ super(identifier, sequence, retry, replyTo);
+ this.mod = Preconditions.checkNotNull(mod);
+ this.coordinated = coordinated;
+ }
+
+
+ private CommitLocalTransactionRequest(final CommitLocalTransactionRequest request, final long retry) {
+ super(request, retry);
+ this.mod = request.mod;
+ this.coordinated = request.coordinated;
+ }
+
+ public DataTreeModification getModification() {
+ return mod;
+ }
+
+ /**
+ * Indicate if this is a coordinated, multi-backend request. If this method returns true, the backend must
+ * act as a cohort participating in the three-phase commit (3PC) protocol to commit this transaction. If this
+ * method returns false, the backend should proceed to commit the transaction and respond once the commit completes
+ * or fails to complete.
+ *
+ * @return Indication of coordinated commit.
+ */
+ public boolean isCoordinated() {
+ return coordinated;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return super.addToStringAttributes(toStringHelper).add("coordinated", coordinated);
+ }
+
+ @Override
+ protected CommitLocalTransactionRequest cloneAsRetry(final long retry) {
+ return new CommitLocalTransactionRequest(this, retry);
+ }
+}
\ No newline at end of file
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * A transaction request to query if a particular path exists in the current view of a particular transaction.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class ExistsTransactionRequest extends AbstractReadTransactionRequest<ExistsTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+
+ public ExistsTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final @Nonnull ActorRef replyTo, final @Nonnull YangInstanceIdentifier path) {
+ this(identifier, sequence, 0, replyTo, path);
+ }
+
+ ExistsTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final long retry, final @Nonnull ActorRef replyTo, final @Nonnull YangInstanceIdentifier path) {
+ super(identifier, sequence, retry, replyTo, path);
+ }
+
+ private ExistsTransactionRequest(final ExistsTransactionRequest request, final ABIVersion version) {
+ super(request, version);
+ }
+
+ private ExistsTransactionRequest(final ExistsTransactionRequest request, final long retry) {
+ super(request, retry);
+ }
+
+ @Override
+ protected ExistsTransactionRequest cloneAsVersion(final ABIVersion version) {
+ return new ExistsTransactionRequest(this, version);
+ }
+
+ @Override
+ protected ExistsTransactionRequestProxyV1 externalizableProxy(final ABIVersion version) {
+ return new ExistsTransactionRequestProxyV1(this);
+ }
+
+ @Override
+ protected ExistsTransactionRequest cloneAsRetry(final long retry) {
+ return new ExistsTransactionRequest(this, retry);
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * Externalizable proxy for use with {@link ExistsTransactionRequest}. It implements the initial (Boron) serialization
+ * format.
+ *
+ * @author Robert Varga
+ */
+final class ExistsTransactionRequestProxyV1 extends AbstractReadTransactionRequestProxyV1<ExistsTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+
+ public ExistsTransactionRequestProxyV1() {
+ // For Externalizable
+ }
+
+ ExistsTransactionRequestProxyV1(final ExistsTransactionRequest request) {
+ super(request);
+ }
+
+ @Override
+ ExistsTransactionRequest createReadRequest(final TransactionIdentifier target, final long sequence,
+ final long retry, final ActorRef replyTo, final YangInstanceIdentifier path) {
+ return new ExistsTransactionRequest(target, sequence, retry, replyTo, path);
+ }
+}
\ No newline at end of file
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Successuful reply to an {@link ExistsTransactionRequest}. It indicates presence of requested data via
+ * {@link #getExists()}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class ExistsTransactionSuccess extends TransactionSuccess<ExistsTransactionSuccess> {
+ private static final long serialVersionUID = 1L;
+ private final boolean exists;
+
+ public ExistsTransactionSuccess(final TransactionIdentifier target, final long sequence, final boolean exists) {
+ this(target, sequence, 0, exists);
+ }
+
+ ExistsTransactionSuccess(final TransactionIdentifier target, final long sequence, final long retry,
+ final boolean exists) {
+ super(target, sequence, retry);
+ this.exists = exists;
+ }
+
+ public boolean getExists() {
+ return exists;
+ }
+
+ @Override
+ protected ExistsTransactionSuccessProxyV1 externalizableProxy(final ABIVersion version) {
+ return new ExistsTransactionSuccessProxyV1(this);
+ }
+
+ @Override
+ protected ExistsTransactionSuccess cloneAsVersion(final ABIVersion version) {
+ return this;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return super.addToStringAttributes(toStringHelper).add("exists", exists);
+ }
+}
--- /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.commands;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Externalizable proxy for use with {@link ExistsTransactionSuccess}. It implements the initial (Boron) serialization
+ * format.
+ *
+ * @author Robert Varga
+ */
+final class ExistsTransactionSuccessProxyV1 extends AbstractTransactionSuccessProxy<ExistsTransactionSuccess> {
+ private static final long serialVersionUID = 1L;
+ private boolean exists;
+
+ public ExistsTransactionSuccessProxyV1() {
+ // For Externalizable
+ }
+
+ ExistsTransactionSuccessProxyV1(final ExistsTransactionSuccess request) {
+ super(request);
+ this.exists = request.getExists();
+ }
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeBoolean(exists);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ exists = in.readBoolean();
+ }
+
+ @Override
+ protected ExistsTransactionSuccess createSuccess(final TransactionIdentifier target, final long sequence,
+ final long retry) {
+ return new ExistsTransactionSuccess(target, sequence, retry, exists);
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.Optional;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * A transaction request to apply a particular set of operations on top of the current transaction. This message is
+ * used to also finish a transaction by specifying a {@link PersistenceProtocol}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class ModifyTransactionRequest extends TransactionRequest<ModifyTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+ private final List<TransactionModification> modifications;
+ private final PersistenceProtocol protocol;
+
+ private ModifyTransactionRequest(final ModifyTransactionRequest request, final long retry) {
+ super(request, retry);
+ this.modifications = request.modifications;
+ this.protocol = request.protocol;
+ }
+
+ ModifyTransactionRequest(final TransactionIdentifier target, final long sequence, final long retry,
+ final ActorRef replyTo, final List<TransactionModification> modifications, final PersistenceProtocol protocol) {
+ super(target, sequence, retry, replyTo);
+ this.modifications = ImmutableList.copyOf(modifications);
+ this.protocol = protocol;
+ }
+
+ public Optional<PersistenceProtocol> getPersistenceProtocol() {
+ return Optional.ofNullable(protocol);
+ }
+
+ public List<TransactionModification> getModifications() {
+ return modifications;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return super.addToStringAttributes(toStringHelper).add("operations", modifications).add("protocol", protocol);
+ }
+
+ @Override
+ protected ModifyTransactionRequestProxyV1 externalizableProxy(final ABIVersion version) {
+ return new ModifyTransactionRequestProxyV1(this);
+ }
+
+ @Override
+ protected ModifyTransactionRequest cloneAsRetry(final long retry) {
+ return new ModifyTransactionRequest(this, retry);
+ }
+
+ @Override
+ protected ModifyTransactionRequest cloneAsVersion(final ABIVersion version) {
+ return this;
+ }
+
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.concurrent.NotThreadSafe;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.concepts.Identifiable;
+
+/**
+ * A reusable {@link Builder} for creating {@link ModifyTransactionRequest} message instances. Its internal state is
+ * reset when {@link #build()} is invoked, hence it can be used to create a sequence of messages.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NotThreadSafe
+public final class ModifyTransactionRequestBuilder implements Builder<ModifyTransactionRequest>,
+ Identifiable<TransactionIdentifier> {
+ private final List<TransactionModification> modifications = new ArrayList<>(1);
+ private final TransactionIdentifier identifier;
+ private final ActorRef replyTo;
+ private PersistenceProtocol protocol = null;
+ private long sequence;
+
+ public ModifyTransactionRequestBuilder(final TransactionIdentifier identifier, final ActorRef replyTo) {
+ this.identifier = Preconditions.checkNotNull(identifier);
+ this.replyTo = Preconditions.checkNotNull(replyTo);
+ }
+
+ @Override
+ public TransactionIdentifier getIdentifier() {
+ return identifier;
+ }
+
+ private void checkFinished() {
+ Preconditions.checkState(protocol != null, "Batch has already been finished");
+ }
+
+ public void setSequence(final long sequence) {
+ checkFinished();
+ Preconditions.checkState(modifications.isEmpty(), "Sequence must be set first");
+ this.sequence = sequence;
+ }
+
+ public void addModification(final TransactionModification modification) {
+ checkFinished();
+ modifications.add(Preconditions.checkNotNull(modification));
+ }
+
+ public void setAbort() {
+ checkFinished();
+ // Transaction is being aborted, no need to transmit operations
+ modifications.clear();
+ protocol = PersistenceProtocol.ABORT;
+ }
+
+ public void setCommit(final boolean coordinated) {
+ checkFinished();
+ protocol = coordinated ? PersistenceProtocol.THREE_PHASE : PersistenceProtocol.SIMPLE;
+ }
+
+ public int size() {
+ return modifications.size();
+ }
+
+ @Override
+ public ModifyTransactionRequest build() {
+ final ModifyTransactionRequest ret = new ModifyTransactionRequest(identifier, sequence, 0, replyTo,
+ modifications, protocol);
+ modifications.clear();
+ protocol = null;
+ sequence = 0;
+ return ret;
+ }
+
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataInput;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputOutput;
+
+/**
+ * Externalizable proxy for use with {@link ExistsTransactionRequest}. It implements the initial (Boron) serialization
+ * format.
+ *
+ * @author Robert Varga
+ */
+final class ModifyTransactionRequestProxyV1 extends AbstractTransactionRequestProxy<ModifyTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+ private List<TransactionModification> modifications;
+ private Optional<PersistenceProtocol> protocol;
+
+ public ModifyTransactionRequestProxyV1() {
+ // For Externalizable
+ }
+
+ ModifyTransactionRequestProxyV1(final ModifyTransactionRequest request) {
+ super(request);
+ this.modifications = Preconditions.checkNotNull(request.getModifications());
+ this.protocol = request.getPersistenceProtocol();
+ }
+
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+
+ protocol = Optional.ofNullable(PersistenceProtocol.readFrom(in));
+
+ final int size = in.readInt();
+ if (size != 0) {
+ modifications = new ArrayList<>(size);
+ final NormalizedNodeDataInput nnin = NormalizedNodeInputOutput.newDataInput(in);
+ for (int i = 0; i < size; ++i) {
+ modifications.add(TransactionModification.readFrom(nnin));
+ }
+ } else {
+ modifications = ImmutableList.of();
+ }
+ }
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+
+ out.writeByte(PersistenceProtocol.byteValue(protocol.orElse(null)));
+ out.writeInt(modifications.size());
+ if (!modifications.isEmpty()) {
+ try (NormalizedNodeDataOutput nnout = NormalizedNodeInputOutput.newDataOutput(out)) {
+ for (TransactionModification op : modifications) {
+ op.writeTo(nnout);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected ModifyTransactionRequest createRequest(final TransactionIdentifier target, final long sequence,
+ final long retry, final ActorRef replyTo) {
+ return new ModifyTransactionRequest(target, sequence, retry, replyTo, modifications, protocol.orElse(null));
+ }
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import org.opendaylight.yangtools.concepts.WritableObject;
+
+/**
+ * Enumeration of transaction persistence protocols. These govern which protocol is executed between the frontend
+ * and backend to drive persistence of a particular transaction.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public enum PersistenceProtocol implements WritableObject {
+ /**
+ * Abort protocol. The transaction has been aborted on the frontend and its effects should not be visible
+ * in the global history. This is a simple request/reply protocol.
+ */
+ ABORT {
+ @Override
+ byte byteValue() {
+ return 1;
+ }
+ },
+ /**
+ * Simple commit protocol. The transaction should be committed to the global history. The receiving backend
+ * it the only entity which needs to persist its effects, hence a simple request/reply protocol is sufficient.
+ */
+ SIMPLE {
+ @Override
+ byte byteValue() {
+ return 2;
+ }
+ },
+ /**
+ * Three-phase commit protocol (3PC). The transaction should be committed to the global history, but it is a part
+ * of a transaction spanning multiple entities and coordination is needed to drive persistence.
+ */
+ THREE_PHASE {
+ @Override
+ byte byteValue() {
+ return 3;
+ }
+
+ };
+
+ @Override
+ public final void writeTo(final DataOutput out) throws IOException {
+ out.writeByte(byteValue());
+ }
+
+ abstract byte byteValue();
+
+ public static PersistenceProtocol readFrom(final DataInput in) throws IOException {
+ return valueOf(in.readByte());
+ }
+
+ static int byteValue(final PersistenceProtocol finish) {
+ return finish == null ? 0 : finish.byteValue();
+ }
+
+ static PersistenceProtocol valueOf(final byte b) {
+ switch (b) {
+ case 0:
+ return null;
+ case 1:
+ return ABORT;
+ case 2:
+ return SIMPLE;
+ case 3:
+ return THREE_PHASE;
+ default:
+ throw new IllegalArgumentException("Unhandled byte value " + b);
+ }
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * A transaction request to read a particular path exists in the current view of a particular transaction.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class ReadTransactionRequest extends AbstractReadTransactionRequest<ReadTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+
+ public ReadTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final @Nonnull ActorRef replyTo, final @Nonnull YangInstanceIdentifier path) {
+ this(identifier, sequence, 0, replyTo, path);
+ }
+
+ ReadTransactionRequest(final @Nonnull TransactionIdentifier identifier, final long sequence,
+ final long retry, final @Nonnull ActorRef replyTo, final @Nonnull YangInstanceIdentifier path) {
+ super(identifier, sequence, retry, replyTo, path);
+ }
+
+ private ReadTransactionRequest(final ReadTransactionRequest request, final ABIVersion version) {
+ super(request, version);
+ }
+
+ private ReadTransactionRequest(final ReadTransactionRequest request, final long retry) {
+ super(request, retry);
+ }
+
+ @Override
+ protected ReadTransactionRequest cloneAsRetry(final long retry) {
+ return new ReadTransactionRequest(this, retry);
+ }
+
+ @Override
+ protected ReadTransactionRequest cloneAsVersion(final ABIVersion version) {
+ return new ReadTransactionRequest(this, version);
+ }
+
+ @Override
+ protected ReadTransactionRequestProxyV1 externalizableProxy(final ABIVersion version) {
+ return new ReadTransactionRequestProxyV1(this);
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * Externalizable proxy for use with {@link ReadTransactionRequest}. It implements the initial (Boron) serialization
+ * format.
+ *
+ * @author Robert Varga
+ */
+final class ReadTransactionRequestProxyV1 extends AbstractReadTransactionRequestProxyV1<ReadTransactionRequest> {
+ private static final long serialVersionUID = 1L;
+
+ public ReadTransactionRequestProxyV1() {
+ // For Externalizable
+ }
+
+ ReadTransactionRequestProxyV1(final ReadTransactionRequest request) {
+ super(request);
+ }
+
+ @Override
+ ReadTransactionRequest createReadRequest(final TransactionIdentifier target, final long sequence, final long retry,
+ final ActorRef replyTo, final YangInstanceIdentifier path) {
+ return new ReadTransactionRequest(target, sequence, retry, replyTo, path);
+ }
+}
\ No newline at end of file
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Successful reply to an {@link ReadTransactionRequest}. It indicates presence of requested data via {@link #getData()}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class ReadTransactionSuccess extends TransactionSuccess<ReadTransactionSuccess> {
+ private static final long serialVersionUID = 1L;
+ private final Optional<NormalizedNode<?, ?>> data;
+
+ public ReadTransactionSuccess(final TransactionIdentifier identifier, final long sequence,
+ final Optional<NormalizedNode<?, ?>> data) {
+ this(identifier, sequence, 0, data);
+ }
+
+ ReadTransactionSuccess(final TransactionIdentifier identifier, final long sequence, final long retry,
+ final Optional<NormalizedNode<?, ?>> data) {
+ super(identifier, sequence, retry);
+ this.data = Preconditions.checkNotNull(data);
+ }
+
+ public Optional<NormalizedNode<?, ?>> getData() {
+ return data;
+ }
+
+ @Override
+ protected AbstractTransactionSuccessProxy<ReadTransactionSuccess> externalizableProxy(final ABIVersion version) {
+ return new ReadTransactionSuccessProxyV1(this);
+ }
+
+ @Override
+ protected ReadTransactionSuccess cloneAsVersion(final ABIVersion version) {
+ return this;
+ }
+}
--- /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.commands;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputOutput;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Externalizable proxy for use with {@link ReadTransactionSuccess}. It implements the initial (Boron) serialization
+ * format.
+ *
+ * @author Robert Varga
+ */
+final class ReadTransactionSuccessProxyV1 extends AbstractTransactionSuccessProxy<ReadTransactionSuccess> {
+ private static final long serialVersionUID = 1L;
+ private Optional<NormalizedNode<?, ?>> data;
+
+ public ReadTransactionSuccessProxyV1() {
+ // For Externalizable
+ }
+
+ ReadTransactionSuccessProxyV1(final ReadTransactionSuccess request) {
+ super(request);
+ this.data = request.getData();
+ }
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+
+ if (data.isPresent()) {
+ out.writeBoolean(true);
+ try (NormalizedNodeDataOutput nnout = NormalizedNodeInputOutput.newDataOutput(out)) {
+ nnout.writeNormalizedNode(data.get());
+ }
+ } else {
+ out.writeBoolean(false);
+ }
+
+ out.writeObject(data);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+
+ if (in.readBoolean()) {
+ data = Optional.of(NormalizedNodeInputOutput.newDataInput(in).readNormalizedNode());
+ } else {
+ data = Optional.absent();
+ }
+ }
+
+ @Override
+ protected ReadTransactionSuccess createSuccess(final TransactionIdentifier target, final long sequence,
+ final long retry) {
+ return new ReadTransactionSuccess(target, sequence, retry, data);
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Successful reply to a coordinated commit request. It contains a reference to the actor which is handling the commit
+ * process.
+ *
+ * @author Robert Varga
+ */
+public final class TransactionCanCommitSuccess extends TransactionSuccess<TransactionCanCommitSuccess> {
+ private static final long serialVersionUID = 1L;
+ private final ActorRef cohort;
+
+ public TransactionCanCommitSuccess(final TransactionIdentifier identifier, final long sequence, final long retry,
+ final ActorRef cohort) {
+ super(identifier, sequence, retry);
+ this.cohort = Preconditions.checkNotNull(cohort);
+ }
+
+ public ActorRef getCohort() {
+ return cohort;
+ }
+
+ @Override
+ protected AbstractTransactionSuccessProxy<TransactionCanCommitSuccess> externalizableProxy(final ABIVersion version) {
+ return new TransactionCanCommitSuccessProxyV1(this);
+ }
+
+ @Override
+ protected TransactionCanCommitSuccess cloneAsVersion(final ABIVersion version) {
+ return this;
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import akka.serialization.JavaSerializer;
+import akka.serialization.Serialization;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Externalizable proxy for use with {@link TransactionCanCommitSuccess}. It implements the initial (Boron)
+ * serialization format.
+ *
+ * @author Robert Varga
+ */
+final class TransactionCanCommitSuccessProxyV1 extends AbstractTransactionSuccessProxy<TransactionCanCommitSuccess> {
+ private static final long serialVersionUID = 1L;
+ private ActorRef cohort;
+
+ public TransactionCanCommitSuccessProxyV1() {
+ // For Externalizable
+ }
+
+ TransactionCanCommitSuccessProxyV1(final TransactionCanCommitSuccess success) {
+ super(success);
+ this.cohort = success.getCohort();
+ }
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeUTF(Serialization.serializedActorPath(cohort));
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ cohort = JavaSerializer.currentSystem().value().provider().resolveActorRef(in.readUTF());
+ }
+
+ @Override
+ protected TransactionCanCommitSuccess createSuccess(final TransactionIdentifier target, final long sequence,
+ final long retry) {
+ return new TransactionCanCommitSuccess(target, sequence, retry, cohort);
+ }
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * A {@link TransactionModification} which has a data component.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public abstract class TransactionDataModification extends TransactionModification {
+ private final NormalizedNode<?, ?> data;
+
+ TransactionDataModification(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ super(path);
+ this.data = Preconditions.checkNotNull(data);
+ }
+
+ public final NormalizedNode<?, ?> getData() {
+ return data;
+ }
+
+ @Override
+ final void writeTo(final NormalizedNodeDataOutput out) throws IOException {
+ super.writeTo(out);
+ out.writeNormalizedNode(data);
+ }
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * Delete a particular path.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class TransactionDelete extends TransactionModification {
+ public TransactionDelete(final YangInstanceIdentifier path) {
+ super(path);
+ }
+
+ @Override
+ byte getType() {
+ return TYPE_DELETE;
+ }
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.RequestException;
+import org.opendaylight.controller.cluster.access.concepts.RequestFailure;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Generic {@link RequestFailure} involving a {@link TransactionRequest}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class TransactionFailure extends RequestFailure<TransactionIdentifier, TransactionFailure> {
+ private static final long serialVersionUID = 1L;
+
+ TransactionFailure(final TransactionIdentifier target, final long sequence, final long retry,
+ final RequestException cause) {
+ super(target, sequence, retry, cause);
+ }
+
+ @Override
+ protected TransactionFailure cloneAsVersion(final ABIVersion version) {
+ return this;
+ }
+
+ @Override
+ protected TransactionFailureProxyV1 externalizableProxy(final ABIVersion version) {
+ return new TransactionFailureProxyV1(this);
+ }
+}
--- /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.commands;
+
+import java.io.DataInput;
+import java.io.IOException;
+import org.opendaylight.controller.cluster.access.concepts.AbstractRequestFailureProxy;
+import org.opendaylight.controller.cluster.access.concepts.RequestException;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Externalizable proxy for use with {@link TransactionFailure}. It implements the initial (Boron) serialization
+ * format.
+ *
+ * @author Robert Varga
+ */
+final class TransactionFailureProxyV1 extends AbstractRequestFailureProxy<TransactionIdentifier, TransactionFailure> {
+ private static final long serialVersionUID = 1L;
+
+ public TransactionFailureProxyV1() {
+ // For Externalizable
+ }
+
+ TransactionFailureProxyV1(final TransactionFailure failure) {
+ super(failure);
+ }
+
+ @Override
+ protected TransactionFailure createFailure(final TransactionIdentifier target, final long sequence,
+ final long retry, final RequestException cause) {
+ return new TransactionFailure(target, sequence, retry, cause);
+ }
+
+ @Override
+ protected TransactionIdentifier readTarget(final DataInput in) throws IOException {
+ return TransactionIdentifier.readFrom(in);
+ }
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Merge a {@link NormalizedNode} tree onto a specific path.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class TransactionMerge extends TransactionDataModification {
+ public TransactionMerge(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ super(path, data);
+ }
+
+ @Override
+ byte getType() {
+ return TYPE_MERGE;
+ }
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataInput;
+import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * An individual modification of a transaction's state. This class and its subclasses are not serializable, but rather
+ * expose {@link #writeTo(NormalizedNodeDataOutput)} and {@link #readFrom(NormalizedNodeDataInput)} methods for explicit
+ * serialization. The reason for this is that they are usually transmitted in bulk, hence it is advantageous to reuse
+ * a {@link NormalizedNodeDataOutput} instance to achieve better compression.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public abstract class TransactionModification {
+ static final byte TYPE_DELETE = 1;
+ static final byte TYPE_MERGE = 2;
+ static final byte TYPE_WRITE = 3;
+
+ private final YangInstanceIdentifier path;
+
+ TransactionModification(final YangInstanceIdentifier path) {
+ this.path = Preconditions.checkNotNull(path);
+ }
+
+ public final YangInstanceIdentifier getPath() {
+ return path;
+ }
+
+ abstract byte getType();
+
+ void writeTo(final NormalizedNodeDataOutput out) throws IOException {
+ out.writeByte(getType());
+ out.writeYangInstanceIdentifier(path);
+ }
+
+ static TransactionModification readFrom(final NormalizedNodeDataInput in) throws IOException {
+ final byte type = in.readByte();
+ switch (type) {
+ case TYPE_DELETE:
+ return new TransactionDelete(in.readYangInstanceIdentifier());
+ case TYPE_MERGE:
+ return new TransactionMerge(in.readYangInstanceIdentifier(), in.readNormalizedNode());
+ case TYPE_WRITE:
+ return new TransactionWrite(in.readYangInstanceIdentifier(), in.readNormalizedNode());
+ default:
+ throw new IllegalArgumentException("Unhandled type " + type);
+ }
+ }
+}
--- /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.commands;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.Beta;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.Request;
+import org.opendaylight.controller.cluster.access.concepts.RequestException;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Abstract base class for {@link Request}s involving specific transaction. This class is visible outside of this
+ * package solely for the ability to perform a unified instanceof check.
+ *
+ * @author Robert Varga
+ *
+ * @param <T> Message type
+ */
+@Beta
+public abstract class TransactionRequest<T extends TransactionRequest<T>> extends Request<TransactionIdentifier, T> {
+ private static final long serialVersionUID = 1L;
+
+ TransactionRequest(final TransactionIdentifier identifier, final long sequence, final long retry,
+ final ActorRef replyTo) {
+ super(identifier, sequence, retry, replyTo);
+ }
+
+ TransactionRequest(final T request, final ABIVersion version) {
+ super(request, version);
+ }
+
+ TransactionRequest(final T request, final long retry) {
+ super(request, retry);
+ }
+
+ @Override
+ public final TransactionFailure toRequestFailure(final RequestException cause) {
+ return new TransactionFailure(getTarget(), getSequence(), getRetry(), cause);
+ }
+
+ @Override
+ protected abstract AbstractTransactionRequestProxy<T> externalizableProxy(final ABIVersion version);
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.controller.cluster.access.ABIVersion;
+import org.opendaylight.controller.cluster.access.concepts.RequestSuccess;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+
+/**
+ * Abstract base class for {@link RequestSuccess}es involving specific transaction. This class is visible outside of
+ * this package solely for the ability to perform a unified instanceof check.
+ *
+ * @author Robert Varga
+ *
+ * @param <T> Message type
+ */
+@Beta
+public abstract class TransactionSuccess<T extends TransactionSuccess<T>> extends RequestSuccess<TransactionIdentifier, T> {
+ private static final long serialVersionUID = 1L;
+
+ TransactionSuccess(final TransactionIdentifier identifier, final long sequence, final long retry) {
+ super(identifier, sequence, retry);
+ }
+
+ @Override
+ protected abstract AbstractTransactionSuccessProxy<T> externalizableProxy(ABIVersion version);
+}
--- /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.commands;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Modification to write (and replace) a subtree at specified path with another subtree.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class TransactionWrite extends TransactionDataModification {
+ public TransactionWrite(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ super(path, data);
+ }
+
+ @Override
+ byte getType() {
+ return TYPE_WRITE;
+ }
+}
--- /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
+ */
+/**
+ * This package defines the messages used to interact with the CDS backend implementation.
+ */
+package org.opendaylight.controller.cluster.access.commands;