From 3f10df4865b301abdeff3d916c0eff22156a6eac Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 15 May 2014 15:14:03 +0200 Subject: [PATCH] BUG-509: reorganize data tree abstractions. This patch has no functional changes, it only rearranges code such that the flow of data and object lifecycle becomes more obvious. This will make metadata lifecycle easier to manage. Change-Id: I10fd912433b72e25729d163c27699a5a5c47e305 Signed-off-by: Robert Varga --- .../store/impl/DataAndMetadataSnapshot.java | 87 ------------- .../md/sal/dom/store/impl/DataTree.java | 120 ++++++++++++++++++ .../dom/store/impl/InMemoryDOMDataStore.java | 76 +++++------ .../sal/dom/store/impl/MutableDataTree.java | 14 +- .../impl/ModificationMetadataTreeTest.java | 12 +- 5 files changed, 165 insertions(+), 144 deletions(-) delete mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java deleted file mode 100644 index b540eeaf3a..0000000000 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2014 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.md.sal.dom.store.impl; - -import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.impl.schema.Builders; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; - -import com.google.common.base.Optional; - -class DataAndMetadataSnapshot { - - private final StoreMetadataNode metadataTree; - private final Optional schemaContext; - - private DataAndMetadataSnapshot(final StoreMetadataNode metadataTree, final Optional schemaCtx) { - this.metadataTree = metadataTree; - this.schemaContext = schemaCtx; - } - - public static Builder builder() { - return new Builder(); - } - - public static DataAndMetadataSnapshot createEmpty() { - return createEmpty(new NodeIdentifier(SchemaContext.NAME)); - } - - - public static DataAndMetadataSnapshot createEmpty(final NodeIdentifier rootNode) { - NormalizedNode data = Builders.containerBuilder().withNodeIdentifier(rootNode).build(); - StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data); - return new DataAndMetadataSnapshot(metadata,Optional.absent()); - } - - public static DataAndMetadataSnapshot createEmpty(final SchemaContext ctx) { - NodeIdentifier rootNodeIdentifier = new NodeIdentifier(ctx.getQName()); - NormalizedNode data = Builders.containerBuilder().withNodeIdentifier(rootNodeIdentifier).build(); - StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data); - return new DataAndMetadataSnapshot(metadata, Optional.of(ctx)); - } - - public Optional getSchemaContext() { - return schemaContext; - } - - public NormalizedNode getDataTree() { - return metadataTree.getData(); - } - - public StoreMetadataNode getMetadataTree() { - return metadataTree; - } - - public Optional read(final InstanceIdentifier path) { - return TreeNodeUtils.findNode(metadataTree, path); - } - - public static class Builder { - private StoreMetadataNode metadataTree; - private SchemaContext schemaContext; - - public Builder setMetadataTree(final StoreMetadataNode metadataTree) { - this.metadataTree = metadataTree; - return this; - } - - public Builder setSchemaContext(final SchemaContext schemaContext) { - this.schemaContext = schemaContext; - return this; - } - - public DataAndMetadataSnapshot build() { - return new DataAndMetadataSnapshot(metadataTree, Optional.fromNullable(schemaContext)); - } - - } -} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java new file mode 100644 index 0000000000..3124199006 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 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.md.sal.dom.store.impl; + +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +/** + * Read-only snapshot of the data tree. + */ +final class DataTree { + public static final class Snapshot { + private final SchemaContext schemaContext; + private final StoreMetadataNode rootNode; + + @VisibleForTesting + Snapshot(final SchemaContext schemaContext, final StoreMetadataNode rootNode) { + this.schemaContext = Preconditions.checkNotNull(schemaContext); + this.rootNode = Preconditions.checkNotNull(rootNode); + } + + public SchemaContext getSchemaContext() { + return schemaContext; + } + + public Optional> readNode(final InstanceIdentifier path) { + return NormalizedNodeUtils.findNode(rootNode.getData(), path); + } + + // FIXME: this is a leak of information + @Deprecated + StoreMetadataNode getRootNode() { + return rootNode; + } + + @Override + public String toString() { + return rootNode.getSubtreeVersion().toString(); + } + } + + private static final Logger LOG = LoggerFactory.getLogger(DataTree.class); + private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true); + private StoreMetadataNode rootNode; + private SchemaContext currentSchemaContext; + + private DataTree(StoreMetadataNode rootNode, final SchemaContext schemaContext) { + this.rootNode = Preconditions.checkNotNull(rootNode); + this.currentSchemaContext = schemaContext; + } + + public synchronized void setSchemaContext(final SchemaContext newSchemaContext) { + Preconditions.checkNotNull(newSchemaContext); + + LOG.info("Attepting to install schema context {}", newSchemaContext); + + /* + * FIXME: we should walk the schema contexts, both current and new and see + * whether they are compatible here. Reject incompatible changes. + */ + + // Ready to change the context now, make sure no operations are running + rwLock.writeLock().lock(); + try { + this.currentSchemaContext = newSchemaContext; + } finally { + rwLock.writeLock().unlock(); + } + } + + public static DataTree create(final SchemaContext schemaContext) { + final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME); + final NormalizedNode data = Builders.containerBuilder().withNodeIdentifier(root).build(); + + return new DataTree(StoreMetadataNode.createEmpty(data), schemaContext); + } + + public Snapshot takeSnapshot() { + rwLock.readLock().lock(); + + try { + return new Snapshot(currentSchemaContext, rootNode); + } finally { + rwLock.readLock().unlock(); + } + } + + public void commitSnapshot(Snapshot currentSnapshot, StoreMetadataNode newDataTree) { + // Ready to change the context now, make sure no operations are running + rwLock.writeLock().lock(); + try { + Preconditions.checkState(currentSnapshot.rootNode == rootNode, + String.format("Store snapshot %s and transaction snapshot %s differ.", + rootNode, currentSnapshot.rootNode)); + + this.rootNode = newDataTree; + } finally { + rwLock.writeLock().unlock(); + } + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java index e848a51a66..7d2ff30b1f 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java @@ -14,7 +14,6 @@ import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.incre import java.util.Collections; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener; @@ -34,7 +33,6 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; import org.slf4j.Logger; @@ -57,19 +55,13 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private final ListeningExecutorService executor; private final String name; private final AtomicLong txCounter = new AtomicLong(0); - private final ListenerTree listenerTree; - private final AtomicReference snapshot; - - private ModificationApplyOperation operationTree; - - private SchemaContext schemaContext; + private final ListenerTree listenerTree = ListenerTree.create(); + private final DataTree dataTree = DataTree.create(null); + private ModificationApplyOperation operationTree = new AlwaysFailOperation(); public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) { this.name = Preconditions.checkNotNull(name); this.executor = Preconditions.checkNotNull(executor); - this.listenerTree = ListenerTree.create(); - this.snapshot = new AtomicReference(DataAndMetadataSnapshot.createEmpty()); - this.operationTree = new AlwaysFailOperation(); } @Override @@ -79,23 +71,30 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public DOMStoreReadTransaction newReadOnlyTransaction() { - return new SnapshotBackedReadTransaction(nextIdentifier(), snapshot.get()); + return new SnapshotBackedReadTransaction(nextIdentifier(), dataTree.takeSnapshot()); } @Override public DOMStoreReadWriteTransaction newReadWriteTransaction() { - return new SnapshotBackedReadWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree); + return new SnapshotBackedReadWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree); } @Override public DOMStoreWriteTransaction newWriteOnlyTransaction() { - return new SnapshotBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree); + return new SnapshotBackedWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree); } @Override public synchronized void onGlobalContextUpdated(final SchemaContext ctx) { - operationTree = SchemaAwareApplyOperationRoot.from(ctx); - schemaContext = ctx; + /* + * Order of operations is important: dataTree may reject the context + * and creation of ModificationApplyOperation may fail. So pre-construct + * the operation, then update the data tree and then move the operation + * into view. + */ + final ModificationApplyOperation newOperationTree = SchemaAwareApplyOperationRoot.from(ctx); + dataTree.setSchemaContext(ctx); + operationTree = newOperationTree; } @Override @@ -115,9 +114,9 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch reg = listenerTree.registerDataChangeListener(path, listener, scope); - Optional currentState = snapshot.get().read(path); + Optional> currentState = dataTree.takeSnapshot().readNode(path); if (currentState.isPresent()) { - final NormalizedNode data = currentState.get().getData(); + final NormalizedNode data = currentState.get(); final DOMImmutableDataChangeEvent event = DOMImmutableDataChangeEvent.builder(DataChangeScope.BASE) // .setAfter(data) // @@ -146,27 +145,20 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch return name + "-" + txCounter.getAndIncrement(); } - private void commit(final DataAndMetadataSnapshot currentSnapshot, final StoreMetadataNode newDataTree, + private void commit(final DataTree.Snapshot currentSnapshot, final StoreMetadataNode newDataTree, final ResolveDataChangeEventsTask listenerResolver) { - LOG.debug("Updating Store snaphot version: {} with version:{}", currentSnapshot.getMetadataTree() - .getSubtreeVersion(), newDataTree.getSubtreeVersion()); + LOG.debug("Updating Store snaphot version: {} with version:{}", currentSnapshot, newDataTree.getSubtreeVersion()); if (LOG.isTraceEnabled()) { LOG.trace("Data Tree is {}", StoreUtils.toStringTree(newDataTree.getData())); } - final DataAndMetadataSnapshot newSnapshot = DataAndMetadataSnapshot.builder() // - .setMetadataTree(newDataTree) // - .setSchemaContext(schemaContext) // - .build(); - /* * The commit has to occur atomically with regard to listener * registrations. */ synchronized (this) { - final boolean success = snapshot.compareAndSet(currentSnapshot, newSnapshot); - checkState(success, "Store snapshot and transaction snapshot differ. This should never happen."); + dataTree.commitSnapshot(currentSnapshot, newDataTree); for (ChangeListenerNotifyTask task : listenerResolver.call()) { LOG.trace("Scheduling invocation of listeners: {}", task); @@ -204,15 +196,14 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } } - private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements + private static final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements DOMStoreReadTransaction { - private DataAndMetadataSnapshot stableSnapshot; + private DataTree.Snapshot stableSnapshot; - public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) { + public SnapshotBackedReadTransaction(final Object identifier, final DataTree.Snapshot snapshot) { super(identifier); this.stableSnapshot = Preconditions.checkNotNull(snapshot); - LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree() - .getSubtreeVersion()); + LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot); } @Override @@ -225,7 +216,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch public ListenableFuture>> read(final InstanceIdentifier path) { checkNotNull(path, "Path must not be null."); checkState(stableSnapshot != null, "Transaction is closed"); - return Futures.immediateFuture(NormalizedNodeUtils.findNode(stableSnapshot.getDataTree(), path)); + return Futures.immediateFuture(stableSnapshot.readNode(path)); } } @@ -235,13 +226,12 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private InMemoryDOMDataStore store; private boolean ready = false; - public SnapshotBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot, + public SnapshotBackedWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot, final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) { super(identifier); mutableTree = MutableDataTree.from(snapshot, applyOper); this.store = store; - LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree() - .getSubtreeVersion()); + LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot); } @Override @@ -318,7 +308,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private static class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements DOMStoreReadWriteTransaction { - protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot, + protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot, final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) { super(identifier, snapshot, store, applyOper); } @@ -340,7 +330,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private final SnapshotBackedWriteTransaction transaction; private final NodeModification modification; - private DataAndMetadataSnapshot storeSnapshot; + private DataTree.Snapshot storeSnapshot; private Optional proposedSubtree; private ResolveDataChangeEventsTask listenerResolver; @@ -351,7 +341,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public ListenableFuture canCommit() { - final DataAndMetadataSnapshot snapshotCapture = snapshot.get(); + final DataTree.Snapshot snapshotCapture = dataTree.takeSnapshot(); final ModificationApplyOperation snapshotOperation = operationTree; return executor.submit(new Callable() { @@ -361,7 +351,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch Boolean applicable = false; try { snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification, - Optional.of(snapshotCapture.getMetadataTree())); + Optional.of(snapshotCapture.getRootNode())); applicable = true; } catch (DataPreconditionFailedException e) { LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e); @@ -375,7 +365,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public ListenableFuture preCommit() { - storeSnapshot = snapshot.get(); + storeSnapshot = dataTree.takeSnapshot(); if (modification.getModificationType() == ModificationType.UNMODIFIED) { return Futures.immediateFuture(null); } @@ -383,7 +373,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public Void call() throws Exception { - StoreMetadataNode metadataTree = storeSnapshot.getMetadataTree(); + StoreMetadataNode metadataTree = storeSnapshot.getRootNode(); proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree), increase(metadataTree.getSubtreeVersion())); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java index b711163b46..1002cd54b5 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java @@ -34,13 +34,13 @@ class MutableDataTree { private static final Logger LOG = LoggerFactory.getLogger(MutableDataTree.class); private final AtomicBoolean sealed = new AtomicBoolean(); private final ModificationApplyOperation strategyTree; - private final DataAndMetadataSnapshot snapshot; private final NodeModification rootModification; + private final DataTree.Snapshot snapshot; - private MutableDataTree(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation strategyTree) { - this.snapshot = snapshot; - this.strategyTree = strategyTree; - this.rootModification = NodeModification.createUnmodified(snapshot.getMetadataTree()); + private MutableDataTree(final DataTree.Snapshot snapshot, final ModificationApplyOperation strategyTree) { + this.snapshot = Preconditions.checkNotNull(snapshot); + this.strategyTree = Preconditions.checkNotNull(strategyTree); + this.rootModification = NodeModification.createUnmodified(snapshot.getRootNode()); } public void write(final InstanceIdentifier path, final NormalizedNode value) { @@ -97,7 +97,7 @@ class MutableDataTree { return potentialSnapshot.get(); } return resolveModificationStrategy(path).apply(modification, modification.getOriginal(), - StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion())); + StoreUtils.increase(snapshot.getRootNode().getSubtreeVersion())); } catch (Exception e) { LOG.error("Could not create snapshot for {}:{}", path,modification,e); throw e; @@ -119,7 +119,7 @@ class MutableDataTree { return OperationWithModification.from(operation, modification); } - public static MutableDataTree from(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation resolver) { + public static MutableDataTree from(final DataTree.Snapshot snapshot, final ModificationApplyOperation resolver) { return new MutableDataTree(snapshot, resolver); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationMetadataTreeTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationMetadataTreeTest.java index e14699311b..0445c47c6b 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationMetadataTreeTest.java +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationMetadataTreeTest.java @@ -137,11 +137,9 @@ public class ModificationMetadataTreeTest { @Test public void basicReadWrites() { - MutableDataTree modificationTree = MutableDataTree.from( - DataAndMetadataSnapshot.builder() // - .setMetadataTree(StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))) // - .setSchemaContext(schemaContext) // - .build(), new SchemaAwareApplyOperationRoot(schemaContext)); + MutableDataTree modificationTree = MutableDataTree.from(new DataTree.Snapshot(schemaContext, + StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))), + new SchemaAwareApplyOperationRoot(schemaContext)); Optional> originalBarNode = modificationTree.read(OUTER_LIST_2_PATH); assertTrue(originalBarNode.isPresent()); assertSame(BAR_NODE, originalBarNode.get()); @@ -166,7 +164,7 @@ public class ModificationMetadataTreeTest { /** * Creates empty Snapshot with associated schema context. */ - DataAndMetadataSnapshot emptySnapshot = DataAndMetadataSnapshot.createEmpty(schemaContext); + DataTree t = DataTree.create(schemaContext); /** * @@ -174,7 +172,7 @@ public class ModificationMetadataTreeTest { * context. * */ - MutableDataTree modificationTree = MutableDataTree.from(emptySnapshot, new SchemaAwareApplyOperationRoot( + MutableDataTree modificationTree = MutableDataTree.from(t.takeSnapshot(), new SchemaAwareApplyOperationRoot( schemaContext)); return modificationTree; } -- 2.36.6