import org.opendaylight.controller.cluster.datastore.persisted.CloseLocalHistoryPayload;
import org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload;
import org.opendaylight.controller.cluster.datastore.persisted.CreateLocalHistoryPayload;
+import org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.DataTreeCandidateWithVersion;
import org.opendaylight.controller.cluster.datastore.persisted.MetadataShardDataTreeSnapshot;
import org.opendaylight.controller.cluster.datastore.persisted.PurgeLocalHistoryPayload;
import org.opendaylight.controller.cluster.datastore.persisted.PurgeTransactionPayload;
@SuppressWarnings("checkstyle:IllegalCatch")
private void applyRecoveryCandidate(final CommitTransactionPayload payload) throws IOException {
- final Entry<TransactionIdentifier, DataTreeCandidate> entry = payload.getCandidate();
+ final Entry<TransactionIdentifier, DataTreeCandidateWithVersion> entry = payload.getCandidate();
final DataTreeModification unwrapped = dataTree.takeSnapshot().newModification();
+ // FIXME: CONTROLLER-1923: examine version first
final PruningDataTreeModification mod = wrapWithPruning(unwrapped);
- DataTreeCandidates.applyToModification(mod, entry.getValue());
+ DataTreeCandidates.applyToModification(mod, entry.getValue().getCandidate());
mod.ready();
LOG.trace("{}: Applying recovery modification {}", logContext, unwrapped);
private void applyReplicatedCandidate(final CommitTransactionPayload payload)
throws DataValidationFailedException, IOException {
- final Entry<TransactionIdentifier, DataTreeCandidate> entry = payload.getCandidate();
+ final Entry<TransactionIdentifier, DataTreeCandidateWithVersion> entry = payload.getCandidate();
final TransactionIdentifier identifier = entry.getKey();
LOG.debug("{}: Applying foreign transaction {}", logContext, identifier);
final DataTreeModification mod = dataTree.takeSnapshot().newModification();
- DataTreeCandidates.applyToModification(mod, entry.getValue());
+ // TODO: check version here, which will enable us to perform forward-compatibility transformations
+ DataTreeCandidates.applyToModification(mod, entry.getValue().getCandidate());
mod.ready();
LOG.trace("{}: Applying foreign modification {}", logContext, mod);
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Map.Entry;
import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
+import org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.DataTreeCandidateWithVersion;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.IdentifiablePayload;
import org.opendaylight.yangtools.concepts.Variant;
import org.opendaylight.yangtools.yang.data.api.schema.stream.ReusableStreamReceiver;
private static final Logger LOG = LoggerFactory.getLogger(CommitTransactionPayload.class);
private static final long serialVersionUID = 1L;
- private volatile Entry<TransactionIdentifier, DataTreeCandidate> candidate = null;
+ private volatile Entry<TransactionIdentifier, DataTreeCandidateWithVersion> candidate = null;
CommitTransactionPayload() {
return create(transactionId, candidate, 512);
}
- public Entry<TransactionIdentifier, DataTreeCandidate> getCandidate() throws IOException {
- Entry<TransactionIdentifier, DataTreeCandidate> localCandidate = candidate;
+ public Entry<TransactionIdentifier, DataTreeCandidateWithVersion> getCandidate() throws IOException {
+ Entry<TransactionIdentifier, DataTreeCandidateWithVersion> localCandidate = candidate;
if (localCandidate == null) {
synchronized (this) {
localCandidate = candidate;
return localCandidate;
}
- public final Entry<TransactionIdentifier, DataTreeCandidate> getCandidate(
+ public final Entry<TransactionIdentifier, DataTreeCandidateWithVersion> getCandidate(
final ReusableStreamReceiver receiver) throws IOException {
final DataInput in = newDataInput();
return new SimpleImmutableEntry<>(TransactionIdentifier.readFrom(in),
DataTreeCandidateInputOutput.readDataTreeCandidate(in, receiver));
}
+ @Override
public TransactionIdentifier getIdentifier() {
try {
return getCandidate().getKey();
*/
package org.opendaylight.controller.cluster.datastore.persisted;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import java.io.DataInput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.stream.ReusableStreamReceiver;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeDataInput;
import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeDataOutput;
+import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeStreamVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
}
- public static DataTreeCandidate readDataTreeCandidate(final DataInput in, final ReusableStreamReceiver receiver)
- throws IOException {
+ @NonNullByDefault
+ public static final class DataTreeCandidateWithVersion implements Immutable {
+ private final DataTreeCandidate candidate;
+ private final NormalizedNodeStreamVersion version;
+
+ public DataTreeCandidateWithVersion(final DataTreeCandidate candidate,
+ final NormalizedNodeStreamVersion version) {
+ this.candidate = requireNonNull(candidate);
+ this.version = requireNonNull(version);
+ }
+
+ public DataTreeCandidate getCandidate() {
+ return candidate;
+ }
+
+ public NormalizedNodeStreamVersion getVersion() {
+ return version;
+ }
+ }
+
+ public static DataTreeCandidateWithVersion readDataTreeCandidate(final DataInput in,
+ final ReusableStreamReceiver receiver) throws IOException {
final NormalizedNodeDataInput reader = NormalizedNodeDataInput.newDataInput(in);
final YangInstanceIdentifier rootPath = reader.readYangInstanceIdentifier();
final byte type = reader.readByte();
throw new IllegalArgumentException("Unhandled node type " + type);
}
- return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode);
+ return new DataTreeCandidateWithVersion(DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode),
+ reader.getVersion());
}
private static void writeChildren(final NormalizedNodeDataOutput out,
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.cluster.datastore.AbstractTest;
+import org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.DataTreeCandidateWithVersion;
import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
import org.opendaylight.yangtools.yang.common.QName;
}
}
- private static void assertCandidateEquals(final DataTreeCandidate expected, final DataTreeCandidate actual) {
- assertEquals("root path", expected.getRootPath(), actual.getRootPath());
- assertCandidateNodeEquals(expected.getRootNode(), actual.getRootNode());
+ private static void assertCandidateEquals(final DataTreeCandidate expected,
+ final DataTreeCandidateWithVersion actual) {
+ final DataTreeCandidate candidate = actual.getCandidate();
+ assertEquals("root path", expected.getRootPath(), candidate.getRootPath());
+ assertCandidateNodeEquals(expected.getRootNode(), candidate.getRootNode());
}
private static void assertCandidateNodeEquals(final DataTreeCandidateNode expected,