Expose stream version used for DataTreeCandidate stream 38/87038/8
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 19 Jan 2020 10:53:05 +0000 (11:53 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 19 Jan 2020 18:47:20 +0000 (19:47 +0100)
We need to properly version the payload stream, as it gives us
the view into which version produced it. This allows us to make
proper typing assumptions in normalization (and thus pruning).

JIRA: CONTROLLER-1923
Change-Id: Iaea995a5ac58e1fba2a4199d3355b321cf9fcff3
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardDataTree.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/CommitTransactionPayload.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/DataTreeCandidateInputOutput.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/persisted/CommitTransactionPayloadTest.java

index 016b078..bbcc42c 100644 (file)
@@ -57,6 +57,7 @@ import org.opendaylight.controller.cluster.datastore.persisted.AbstractIdentifia
 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;
@@ -316,10 +317,11 @@ public class ShardDataTree extends ShardDataTreeTransactionParent {
 
     @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);
@@ -367,12 +369,13 @@ public class ShardDataTree extends ShardDataTreeTransactionParent {
 
     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);
index b216413..fed3483 100644 (file)
@@ -27,6 +27,7 @@ import java.io.StreamCorruptedException;
 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;
@@ -47,7 +48,7 @@ public abstract class CommitTransactionPayload extends IdentifiablePayload<Trans
     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() {
 
@@ -73,8 +74,8 @@ public abstract class CommitTransactionPayload extends IdentifiablePayload<Trans
         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;
@@ -86,13 +87,14 @@ public abstract class CommitTransactionPayload extends IdentifiablePayload<Trans
         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();
index 60d70e4..b78bb56 100644 (file)
@@ -7,6 +7,8 @@
  */
 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;
@@ -14,6 +16,8 @@ import java.io.DataOutput;
 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;
@@ -24,6 +28,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
 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;
 
@@ -97,8 +102,28 @@ public final class DataTreeCandidateInputOutput {
         }
     }
 
-    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();
@@ -130,7 +155,8 @@ public final class DataTreeCandidateInputOutput {
                 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,
index e0518a7..c081b89 100644 (file)
@@ -18,6 +18,7 @@ import org.apache.commons.lang3.SerializationUtils;
 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;
@@ -67,9 +68,11 @@ public class CommitTransactionPayloadTest extends AbstractTest {
         }
     }
 
-    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,

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.