Move JournalWriter.getLastIndex()
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / ShardDataTreeTest.java
index 7db9b033b586fc1c0dd62e07e8fb00afde41a0c6..ef6b2448f72bc0aac5f3e157a56bc36204713abf 100644 (file)
@@ -5,15 +5,15 @@
  * 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.datastore;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -33,12 +33,12 @@ import static org.opendaylight.controller.cluster.datastore.ShardDataTreeMocking
 import static org.opendaylight.controller.cluster.datastore.ShardDataTreeMocking.immediatePreCommit;
 
 import com.google.common.base.Ticker;
-import com.google.common.collect.Maps;
 import com.google.common.primitives.UnsignedLong;
 import com.google.common.util.concurrent.FutureCallback;
-import java.math.BigInteger;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -48,33 +48,49 @@ import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mockito;
-import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardStats;
 import org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload;
+import org.opendaylight.controller.cluster.datastore.persisted.MetadataShardDataTreeSnapshot;
+import org.opendaylight.controller.cluster.datastore.persisted.PayloadVersion;
+import org.opendaylight.controller.cluster.datastore.persisted.ShardSnapshotState;
 import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
 import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel;
 import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener;
+import org.opendaylight.yangtools.yang.common.Empty;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
+import org.opendaylight.yangtools.yang.data.tree.api.TreeType;
+import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
+import org.opendaylight.yangtools.yang.data.tree.spi.DataTreeCandidates;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 public class ShardDataTreeTest extends AbstractTest {
+    private static final DatastoreContext DATASTORE_CONTEXT = DatastoreContext.newBuilder().build();
 
     private final Shard mockShard = Mockito.mock(Shard.class);
     private ShardDataTree shardDataTree;
-    private SchemaContext fullSchema;
+    private EffectiveModelContext fullSchema;
 
     @Before
     public void setUp() {
         doReturn(Ticker.systemTicker()).when(mockShard).ticker();
-        doReturn(Mockito.mock(ShardStats.class)).when(mockShard).getShardMBean();
+        doReturn(new ShardStats("shardName", "mxBeanType", mockShard)).when(mockShard).getShardMBean();
+        doReturn(DATASTORE_CONTEXT).when(mockShard).getDatastoreContext();
 
         fullSchema = SchemaContextHelper.full();
 
@@ -122,11 +138,11 @@ public class ShardDataTreeTest extends AbstractTest {
 
         final DataTreeSnapshot snapshot1 = readOnlyShardDataTreeTransaction.getSnapshot();
 
-        final Optional<NormalizedNode<?, ?>> optional = snapshot1.readNode(CarsModel.BASE_PATH);
+        final Optional<NormalizedNode> optional = snapshot1.readNode(CarsModel.BASE_PATH);
 
         assertEquals(expectedCarsPresent, optional.isPresent());
 
-        final Optional<NormalizedNode<?, ?>> optional1 = snapshot1.readNode(PeopleModel.BASE_PATH);
+        final Optional<NormalizedNode> optional1 = snapshot1.readNode(PeopleModel.BASE_PATH);
 
         assertEquals(expectedPeoplePresent, optional1.isPresent());
     }
@@ -139,11 +155,11 @@ public class ShardDataTreeTest extends AbstractTest {
         candidates.add(addCar(shardDataTree));
         candidates.add(removeCar(shardDataTree));
 
-        final NormalizedNode<?, ?> expected = getCars(shardDataTree);
+        final NormalizedNode expected = getCars(shardDataTree);
 
         applyCandidates(shardDataTree, candidates);
 
-        final NormalizedNode<?, ?> actual = getCars(shardDataTree);
+        final NormalizedNode actual = getCars(shardDataTree);
 
         assertEquals(expected, actual);
     }
@@ -158,11 +174,11 @@ public class ShardDataTreeTest extends AbstractTest {
         candidates.add(addCar(shardDataTree));
         candidates.add(removeCar(shardDataTree));
 
-        final NormalizedNode<?, ?> expected = getCars(shardDataTree);
+        final NormalizedNode expected = getCars(shardDataTree);
 
         applyCandidates(shardDataTree, candidates);
 
-        final NormalizedNode<?, ?> actual = getCars(shardDataTree);
+        final NormalizedNode actual = getCars(shardDataTree);
 
         assertEquals(expected, actual);
     }
@@ -173,19 +189,19 @@ public class ShardDataTreeTest extends AbstractTest {
 
         DOMDataTreeChangeListener listener = mock(DOMDataTreeChangeListener.class);
         shardDataTree.registerTreeChangeListener(CarsModel.CAR_LIST_PATH.node(CarsModel.CAR_QNAME), listener,
-            com.google.common.base.Optional.absent(), noop -> { });
+            Optional.empty(), noop -> { });
 
         addCar(shardDataTree, "optima");
 
         verifyOnDataTreeChanged(listener, dtc -> {
-            assertEquals("getModificationType", ModificationType.WRITE, dtc.getRootNode().getModificationType());
+            assertEquals("getModificationType", ModificationType.WRITE, dtc.getRootNode().modificationType());
             assertEquals("getRootPath", CarsModel.newCarPath("optima"), dtc.getRootPath());
         });
 
         addCar(shardDataTree, "sportage");
 
         verifyOnDataTreeChanged(listener, dtc -> {
-            assertEquals("getModificationType", ModificationType.WRITE, dtc.getRootNode().getModificationType());
+            assertEquals("getModificationType", ModificationType.WRITE, dtc.getRootNode().modificationType());
             assertEquals("getRootPath", CarsModel.newCarPath("sportage"), dtc.getRootPath());
         });
 
@@ -196,14 +212,14 @@ public class ShardDataTreeTest extends AbstractTest {
 
         shardDataTree.applySnapshot(newDataTree.takeStateSnapshot());
 
-        Map<YangInstanceIdentifier, ModificationType> expChanges = Maps.newHashMap();
+        Map<YangInstanceIdentifier, ModificationType> expChanges = new HashMap<>();
         expChanges.put(CarsModel.newCarPath("optima"), ModificationType.WRITE);
         expChanges.put(CarsModel.newCarPath("murano"), ModificationType.WRITE);
         expChanges.put(CarsModel.newCarPath("sportage"), ModificationType.DELETE);
         verifyOnDataTreeChanged(listener, dtc -> {
             ModificationType expType = expChanges.remove(dtc.getRootPath());
             assertNotNull("Got unexpected change for " + dtc.getRootPath(), expType);
-            assertEquals("getModificationType", expType, dtc.getRootNode().getModificationType());
+            assertEquals("getModificationType", expType, dtc.getRootNode().modificationType());
         });
 
         if (!expChanges.isEmpty()) {
@@ -219,73 +235,73 @@ public class ShardDataTreeTest extends AbstractTest {
         final ShardDataTreeCohort cohort2 = newShardDataTreeCohort(snapshot ->
             snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
 
-        NormalizedNode<?, ?> peopleNode = PeopleModel.create();
+        NormalizedNode peopleNode = PeopleModel.create();
         final ShardDataTreeCohort cohort3 = newShardDataTreeCohort(snapshot ->
             snapshot.write(PeopleModel.BASE_PATH, peopleNode));
 
         YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
-        MapEntryNode carNode = CarsModel.newCarEntry("optima", new BigInteger("100"));
+        MapEntryNode carNode = CarsModel.newCarEntry("optima", Uint64.valueOf(100));
         final ShardDataTreeCohort cohort4 = newShardDataTreeCohort(snapshot -> snapshot.write(carPath, carNode));
 
         immediateCanCommit(cohort1);
-        final FutureCallback<Void> canCommitCallback2 = coordinatedCanCommit(cohort2);
-        final FutureCallback<Void> canCommitCallback3 = coordinatedCanCommit(cohort3);
-        final FutureCallback<Void> canCommitCallback4 = coordinatedCanCommit(cohort4);
+        final FutureCallback<Empty> canCommitCallback2 = coordinatedCanCommit(cohort2);
+        final FutureCallback<Empty> canCommitCallback3 = coordinatedCanCommit(cohort3);
+        final FutureCallback<Empty> canCommitCallback4 = coordinatedCanCommit(cohort4);
 
         final FutureCallback<DataTreeCandidate> preCommitCallback1 = coordinatedPreCommit(cohort1);
         verify(preCommitCallback1).onSuccess(cohort1.getCandidate());
-        verify(canCommitCallback2).onSuccess(null);
+        verify(canCommitCallback2).onSuccess(Empty.value());
 
         final FutureCallback<DataTreeCandidate> preCommitCallback2 = coordinatedPreCommit(cohort2);
         verify(preCommitCallback2).onSuccess(cohort2.getCandidate());
-        verify(canCommitCallback3).onSuccess(null);
+        verify(canCommitCallback3).onSuccess(Empty.value());
 
         final FutureCallback<DataTreeCandidate> preCommitCallback3 = coordinatedPreCommit(cohort3);
         verify(preCommitCallback3).onSuccess(cohort3.getCandidate());
-        verify(canCommitCallback4).onSuccess(null);
+        verify(canCommitCallback4).onSuccess(Empty.value());
 
         final FutureCallback<DataTreeCandidate> preCommitCallback4 = coordinatedPreCommit(cohort4);
         verify(preCommitCallback4).onSuccess(cohort4.getCandidate());
 
         final FutureCallback<UnsignedLong> commitCallback2 = coordinatedCommit(cohort2);
-        verify(mockShard, never()).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class),
+        verify(mockShard, never()).persistPayload(eq(cohort1.transactionId()), any(CommitTransactionPayload.class),
                 anyBoolean());
         verifyNoMoreInteractions(commitCallback2);
 
         final FutureCallback<UnsignedLong> commitCallback4 = coordinatedCommit(cohort4);
-        verify(mockShard, never()).persistPayload(eq(cohort4.getIdentifier()), any(CommitTransactionPayload.class),
+        verify(mockShard, never()).persistPayload(eq(cohort4.transactionId()), any(CommitTransactionPayload.class),
                 anyBoolean());
         verifyNoMoreInteractions(commitCallback4);
 
         final FutureCallback<UnsignedLong> commitCallback1 = coordinatedCommit(cohort1);
         InOrder inOrder = inOrder(mockShard);
-        inOrder.verify(mockShard).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort1.transactionId()), any(CommitTransactionPayload.class),
                 eq(true));
-        inOrder.verify(mockShard).persistPayload(eq(cohort2.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort2.transactionId()), any(CommitTransactionPayload.class),
                 eq(false));
         verifyNoMoreInteractions(commitCallback1);
         verifyNoMoreInteractions(commitCallback2);
 
         final FutureCallback<UnsignedLong> commitCallback3 = coordinatedCommit(cohort3);
         inOrder = inOrder(mockShard);
-        inOrder.verify(mockShard).persistPayload(eq(cohort3.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort3.transactionId()), any(CommitTransactionPayload.class),
                 eq(true));
-        inOrder.verify(mockShard).persistPayload(eq(cohort4.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort4.transactionId()), any(CommitTransactionPayload.class),
                 eq(false));
         verifyNoMoreInteractions(commitCallback3);
         verifyNoMoreInteractions(commitCallback4);
 
         final ShardDataTreeCohort cohort5 = newShardDataTreeCohort(snapshot ->
             snapshot.merge(CarsModel.BASE_PATH, CarsModel.emptyContainer()));
-        final FutureCallback<Void> canCommitCallback5 = coordinatedCanCommit(cohort5);
+        final FutureCallback<Empty> canCommitCallback5 = coordinatedCanCommit(cohort5);
 
         // The payload instance doesn't matter - it just needs to be of type CommitTransactionPayload.
         CommitTransactionPayload mockPayload = CommitTransactionPayload.create(nextTransactionId(),
                 cohort1.getCandidate());
-        shardDataTree.applyReplicatedPayload(cohort1.getIdentifier(), mockPayload);
-        shardDataTree.applyReplicatedPayload(cohort2.getIdentifier(), mockPayload);
-        shardDataTree.applyReplicatedPayload(cohort3.getIdentifier(), mockPayload);
-        shardDataTree.applyReplicatedPayload(cohort4.getIdentifier(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort1.transactionId(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort2.transactionId(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort3.transactionId(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort4.transactionId(), mockPayload);
 
         inOrder = inOrder(commitCallback1, commitCallback2, commitCallback3, commitCallback4);
         inOrder.verify(commitCallback1).onSuccess(any(UnsignedLong.class));
@@ -293,17 +309,12 @@ public class ShardDataTreeTest extends AbstractTest {
         inOrder.verify(commitCallback3).onSuccess(any(UnsignedLong.class));
         inOrder.verify(commitCallback4).onSuccess(any(UnsignedLong.class));
 
-        verify(canCommitCallback5).onSuccess(null);
+        verify(canCommitCallback5).onSuccess(Empty.value());
 
         final DataTreeSnapshot snapshot =
                 shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
-        Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(carPath);
-        assertEquals("Car node present", true, optional.isPresent());
-        assertEquals("Car node", carNode, optional.get());
-
-        optional = snapshot.readNode(PeopleModel.BASE_PATH);
-        assertEquals("People node present", true, optional.isPresent());
-        assertEquals("People node", peopleNode, optional.get());
+        assertEquals("Car node", Optional.of(carNode), snapshot.readNode(carPath));
+        assertEquals("People node", Optional.of(peopleNode), snapshot.readNode(PeopleModel.BASE_PATH));
     }
 
     @Test
@@ -315,7 +326,7 @@ public class ShardDataTreeTest extends AbstractTest {
             snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
 
         YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
-        MapEntryNode carNode = CarsModel.newCarEntry("optima", new BigInteger("100"));
+        MapEntryNode carNode = CarsModel.newCarEntry("optima", Uint64.valueOf(100));
         final ShardDataTreeCohort cohort3 = newShardDataTreeCohort(snapshot -> snapshot.write(carPath, carNode));
 
         final FutureCallback<UnsignedLong> commitCallback2 = immediate3PhaseCommit(cohort2);
@@ -323,19 +334,19 @@ public class ShardDataTreeTest extends AbstractTest {
         final FutureCallback<UnsignedLong> commitCallback1 = immediate3PhaseCommit(cohort1);
 
         InOrder inOrder = inOrder(mockShard);
-        inOrder.verify(mockShard).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort1.transactionId()), any(CommitTransactionPayload.class),
                 eq(true));
-        inOrder.verify(mockShard).persistPayload(eq(cohort2.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort2.transactionId()), any(CommitTransactionPayload.class),
                 eq(true));
-        inOrder.verify(mockShard).persistPayload(eq(cohort3.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort3.transactionId()), any(CommitTransactionPayload.class),
                 eq(false));
 
         // The payload instance doesn't matter - it just needs to be of type CommitTransactionPayload.
         CommitTransactionPayload mockPayload = CommitTransactionPayload.create(nextTransactionId(),
                 cohort1.getCandidate());
-        shardDataTree.applyReplicatedPayload(cohort1.getIdentifier(), mockPayload);
-        shardDataTree.applyReplicatedPayload(cohort2.getIdentifier(), mockPayload);
-        shardDataTree.applyReplicatedPayload(cohort3.getIdentifier(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort1.transactionId(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort2.transactionId(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort3.transactionId(), mockPayload);
 
         inOrder = inOrder(commitCallback1, commitCallback2, commitCallback3);
         inOrder.verify(commitCallback1).onSuccess(any(UnsignedLong.class));
@@ -344,9 +355,7 @@ public class ShardDataTreeTest extends AbstractTest {
 
         final DataTreeSnapshot snapshot =
                 shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
-        Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(carPath);
-        assertEquals("Car node present", true, optional.isPresent());
-        assertEquals("Car node", carNode, optional.get());
+        assertEquals("Car node", Optional.of(carNode), snapshot.readNode(carPath));
     }
 
     @Test
@@ -360,7 +369,7 @@ public class ShardDataTreeTest extends AbstractTest {
             snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
 
         YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
-        MapEntryNode carNode = CarsModel.newCarEntry("optima", new BigInteger("100"));
+        MapEntryNode carNode = CarsModel.newCarEntry("optima", Uint64.valueOf(100));
         final ShardDataTreeCohort cohort3 = newShardDataTreeCohort(snapshot -> snapshot.write(carPath, carNode));
 
         final FutureCallback<UnsignedLong> commitCallback1 = immediate3PhaseCommit(cohort1);
@@ -372,10 +381,9 @@ public class ShardDataTreeTest extends AbstractTest {
         inOrder.verify(commitCallback2).onSuccess(any(UnsignedLong.class));
         inOrder.verify(commitCallback3).onSuccess(any(UnsignedLong.class));
 
-        final DataTreeSnapshot snapshot =
-                shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
-        Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(CarsModel.BASE_PATH);
-        assertEquals("Car node present", true, optional.isPresent());
+        final DataTreeSnapshot snapshot = shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
+        Optional<NormalizedNode> optional = snapshot.readNode(CarsModel.BASE_PATH);
+        assertTrue("Car node present", optional.isPresent());
     }
 
     @SuppressWarnings("unchecked")
@@ -391,7 +399,7 @@ public class ShardDataTreeTest extends AbstractTest {
             snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
 
         YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
-        MapEntryNode carNode = CarsModel.newCarEntry("optima", new BigInteger("100"));
+        MapEntryNode carNode = CarsModel.newCarEntry("optima", Uint64.valueOf(100));
         final ShardDataTreeCohort cohort4 = newShardDataTreeCohort(snapshot -> snapshot.write(carPath, carNode));
 
         coordinatedCanCommit(cohort2);
@@ -403,10 +411,10 @@ public class ShardDataTreeTest extends AbstractTest {
         coordinatedPreCommit(cohort2);
         coordinatedPreCommit(cohort3);
 
-        FutureCallback<Void> mockAbortCallback = mock(FutureCallback.class);
-        doNothing().when(mockAbortCallback).onSuccess(null);
+        FutureCallback<Empty> mockAbortCallback = mock(FutureCallback.class);
+        doNothing().when(mockAbortCallback).onSuccess(Empty.value());
         cohort2.abort(mockAbortCallback);
-        verify(mockAbortCallback).onSuccess(null);
+        verify(mockAbortCallback).onSuccess(Empty.value());
 
         coordinatedPreCommit(cohort4);
         coordinatedCommit(cohort1);
@@ -414,25 +422,24 @@ public class ShardDataTreeTest extends AbstractTest {
         coordinatedCommit(cohort4);
 
         InOrder inOrder = inOrder(mockShard);
-        inOrder.verify(mockShard).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort1.transactionId()), any(CommitTransactionPayload.class),
                 eq(false));
-        inOrder.verify(mockShard).persistPayload(eq(cohort3.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort3.transactionId()), any(CommitTransactionPayload.class),
                 eq(false));
-        inOrder.verify(mockShard).persistPayload(eq(cohort4.getIdentifier()), any(CommitTransactionPayload.class),
+        inOrder.verify(mockShard).persistPayload(eq(cohort4.transactionId()), any(CommitTransactionPayload.class),
                 eq(false));
 
         // The payload instance doesn't matter - it just needs to be of type CommitTransactionPayload.
         CommitTransactionPayload mockPayload = CommitTransactionPayload.create(nextTransactionId(),
                 cohort1.getCandidate());
-        shardDataTree.applyReplicatedPayload(cohort1.getIdentifier(), mockPayload);
-        shardDataTree.applyReplicatedPayload(cohort3.getIdentifier(), mockPayload);
-        shardDataTree.applyReplicatedPayload(cohort4.getIdentifier(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort1.transactionId(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort3.transactionId(), mockPayload);
+        shardDataTree.applyReplicatedPayload(cohort4.transactionId(), mockPayload);
 
         final DataTreeSnapshot snapshot =
                 shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
-        Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(carPath);
-        assertEquals("Car node present", true, optional.isPresent());
-        assertEquals("Car node", carNode, optional.get());
+        Optional<NormalizedNode> optional = snapshot.readNode(carPath);
+        assertEquals("Car node", Optional.of(carNode), optional);
     }
 
     @SuppressWarnings("unchecked")
@@ -446,20 +453,20 @@ public class ShardDataTreeTest extends AbstractTest {
         final ShardDataTreeCohort cohort2 = newShardDataTreeCohort(snapshot ->
             snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
 
-        NormalizedNode<?, ?> peopleNode = PeopleModel.create();
+        NormalizedNode peopleNode = PeopleModel.create();
         final ShardDataTreeCohort cohort3 = newShardDataTreeCohort(snapshot ->
             snapshot.write(PeopleModel.BASE_PATH, peopleNode));
 
         immediateCanCommit(cohort1);
-        FutureCallback<Void> canCommitCallback2 = coordinatedCanCommit(cohort2);
+        FutureCallback<Empty> canCommitCallback2 = coordinatedCanCommit(cohort2);
 
         coordinatedPreCommit(cohort1);
-        verify(canCommitCallback2).onSuccess(null);
+        verify(canCommitCallback2).onSuccess(Empty.value());
 
-        FutureCallback<Void> mockAbortCallback = mock(FutureCallback.class);
-        doNothing().when(mockAbortCallback).onSuccess(null);
+        FutureCallback<Empty> mockAbortCallback = mock(FutureCallback.class);
+        doNothing().when(mockAbortCallback).onSuccess(Empty.value());
         cohort1.abort(mockAbortCallback);
-        verify(mockAbortCallback).onSuccess(null);
+        verify(mockAbortCallback).onSuccess(Empty.value());
 
         FutureCallback<DataTreeCandidate> preCommitCallback2 = coordinatedPreCommit(cohort2);
         verify(preCommitCallback2).onFailure(any(Throwable.class));
@@ -470,9 +477,117 @@ public class ShardDataTreeTest extends AbstractTest {
 
         final DataTreeSnapshot snapshot =
                 shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
-        Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(PeopleModel.BASE_PATH);
-        assertEquals("People node present", true, optional.isPresent());
-        assertEquals("People node", peopleNode, optional.get());
+        Optional<NormalizedNode> optional = snapshot.readNode(PeopleModel.BASE_PATH);
+        assertEquals("People node", Optional.of(peopleNode), optional);
+    }
+
+    @Test
+    public void testUintCommitPayload() throws IOException {
+        shardDataTree.applyRecoveryPayload(CommitTransactionPayload.create(nextTransactionId(),
+            DataTreeCandidates.fromNormalizedNode(YangInstanceIdentifier.of(), bigIntegerRoot()),
+            PayloadVersion.POTASSIUM));
+
+        assertCarsUint64();
+    }
+
+    @Test
+    public void testUintSnapshot() throws IOException, DataValidationFailedException {
+        shardDataTree.applyRecoverySnapshot(new ShardSnapshotState(new MetadataShardDataTreeSnapshot(bigIntegerRoot()),
+            true));
+
+        assertCarsUint64();
+    }
+
+    @Test
+    public void testUintReplay() throws DataValidationFailedException, IOException {
+        // Commit two writes and one merge, saving the data tree candidate for each.
+        //        write(foo=1)
+        //        write(foo=2)
+        //        merge(foo=3)
+        final DataTree dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL,
+            fullSchema);
+        DataTreeModification mod = dataTree.takeSnapshot().newModification();
+        mod.write(CarsModel.BASE_PATH, Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(CarsModel.BASE_QNAME))
+                .withChild(Builders.mapBuilder()
+                    .withNodeIdentifier(new NodeIdentifier(CarsModel.CAR_QNAME))
+                    .withChild(createCar("one", Uint64.ONE))
+                    .build())
+                .build());
+        mod.ready();
+        dataTree.validate(mod);
+        final DataTreeCandidate first = dataTree.prepare(mod);
+        dataTree.commit(first);
+
+        mod = dataTree.takeSnapshot().newModification();
+        mod.write(CarsModel.newCarPath("two"), createCar("two", Uint64.TWO));
+        mod.ready();
+        dataTree.validate(mod);
+        final DataTreeCandidate second = dataTree.prepare(mod);
+        dataTree.commit(second);
+
+        mod = dataTree.takeSnapshot().newModification();
+        mod.merge(CarsModel.CAR_LIST_PATH, Builders.mapBuilder()
+            .withNodeIdentifier(new NodeIdentifier(CarsModel.CAR_QNAME))
+            .withChild(createCar("three", Uint64.TEN))
+            .build());
+        mod.ready();
+        dataTree.validate(mod);
+        final DataTreeCandidate third = dataTree.prepare(mod);
+        dataTree.commit(third);
+
+        // Apply first candidate as a snapshot
+        shardDataTree.applyRecoverySnapshot(new ShardSnapshotState(
+            new MetadataShardDataTreeSnapshot(first.getRootNode().getDataAfter()), true));
+        // Apply the other two snapshots as transactions
+        shardDataTree.applyRecoveryPayload(CommitTransactionPayload.create(nextTransactionId(), second,
+            PayloadVersion.POTASSIUM));
+        shardDataTree.applyRecoveryPayload(CommitTransactionPayload.create(nextTransactionId(), third,
+            PayloadVersion.POTASSIUM));
+
+        // Verify uint translation
+        final DataTreeSnapshot snapshot = shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
+
+        assertEquals(Builders.mapBuilder()
+            .withNodeIdentifier(new NodeIdentifier(CarsModel.CAR_QNAME))
+            // Note: Uint64
+            .withChild(createCar("one", Uint64.ONE))
+            .withChild(createCar("two", Uint64.TWO))
+            .withChild(createCar("three", Uint64.TEN))
+            .build(), snapshot.readNode(CarsModel.CAR_LIST_PATH).orElseThrow());
+    }
+
+    private void assertCarsUint64() {
+        final DataTreeSnapshot snapshot = shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
+        final NormalizedNode cars = snapshot.readNode(CarsModel.CAR_LIST_PATH).orElseThrow();
+
+        assertEquals(Builders.mapBuilder()
+            .withNodeIdentifier(new NodeIdentifier(CarsModel.CAR_QNAME))
+            // Note: Uint64
+            .withChild(createCar("foo", Uint64.ONE))
+            .build(), cars);
+    }
+
+    private static ContainerNode bigIntegerRoot() {
+        return Builders.containerBuilder()
+            .withNodeIdentifier(new NodeIdentifier(SchemaContext.NAME))
+            .withChild(Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(CarsModel.CARS_QNAME))
+                .withChild(Builders.mapBuilder()
+                    .withNodeIdentifier(new NodeIdentifier(CarsModel.CAR_QNAME))
+                    .withChild(createCar("foo", Uint64.ONE))
+                    .build())
+                .build())
+            .build();
+    }
+
+    private static MapEntryNode createCar(final String name, final Object value) {
+        return Builders.mapEntryBuilder()
+            .withNodeIdentifier(NodeIdentifierWithPredicates.of(CarsModel.CAR_QNAME, CarsModel.CAR_NAME_QNAME, name))
+            .withChild(ImmutableNodes.leafNode(CarsModel.CAR_NAME_QNAME, name))
+            // Note: old BigInteger
+            .withChild(ImmutableNodes.leafNode(CarsModel.CAR_PRICE_QNAME, value))
+            .build();
     }
 
     private ShardDataTreeCohort newShardDataTreeCohort(final DataTreeOperation operation) {
@@ -486,7 +601,7 @@ public class ShardDataTreeTest extends AbstractTest {
     @SuppressWarnings({ "rawtypes", "unchecked" })
     private static void verifyOnDataTreeChanged(final DOMDataTreeChangeListener listener,
             final Consumer<DataTreeCandidate> callback) {
-        ArgumentCaptor<Collection> changes = ArgumentCaptor.forClass(Collection.class);
+        ArgumentCaptor<List> changes = ArgumentCaptor.forClass(List.class);
         verify(listener, atLeastOnce()).onDataTreeChanged(changes.capture());
         for (Collection list : changes.getAllValues()) {
             for (Object dtc : list) {
@@ -497,16 +612,16 @@ public class ShardDataTreeTest extends AbstractTest {
         reset(listener);
     }
 
-    private static NormalizedNode<?, ?> getCars(final ShardDataTree shardDataTree) {
+    private static NormalizedNode getCars(final ShardDataTree shardDataTree) {
         final ReadOnlyShardDataTreeTransaction readOnlyShardDataTreeTransaction =
                 shardDataTree.newReadOnlyTransaction(nextTransactionId());
         final DataTreeSnapshot snapshot1 = readOnlyShardDataTreeTransaction.getSnapshot();
 
-        final Optional<NormalizedNode<?, ?>> optional = snapshot1.readNode(CarsModel.BASE_PATH);
+        final Optional<NormalizedNode> optional = snapshot1.readNode(CarsModel.BASE_PATH);
 
-        assertEquals(true, optional.isPresent());
+        assertTrue(optional.isPresent());
 
-        return optional.get();
+        return optional.orElseThrow();
     }
 
     private static DataTreeCandidate addCar(final ShardDataTree shardDataTree) {
@@ -517,7 +632,7 @@ public class ShardDataTreeTest extends AbstractTest {
         return doTransaction(shardDataTree, snapshot -> {
             snapshot.merge(CarsModel.BASE_PATH, CarsModel.emptyContainer());
             snapshot.merge(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode());
-            snapshot.write(CarsModel.newCarPath(name), CarsModel.newCarEntry(name, new BigInteger("100")));
+            snapshot.write(CarsModel.newCarPath(name), CarsModel.newCarEntry(name, Uint64.valueOf(100)));
         });
     }