X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fimpl%2Fschema%2Ftree%2FInMemoryDataTreeModification.java;h=e26c32ee5b03bfc01edd2ec64698a66911797bd0;hb=d0d16d8daa03bb9d1651af08c3751c49d856ac17;hp=206c27372cb0b286ea7545f6d739e9c8869cd81c;hpb=361b6e8e7e578e42a202cfef6d1818d7b6260430;p=yangtools.git diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java index 206c27372c..e26c32ee5b 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java @@ -11,13 +11,14 @@ import java.util.Map.Entry; import javax.annotation.concurrent.GuardedBy; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +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.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version; import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,6 +31,7 @@ final class InMemoryDataTreeModification implements DataTreeModification { private final RootModificationApplyOperation strategyTree; private final InMemoryDataTreeSnapshot snapshot; private final ModifiedNode rootNode; + private final Version version; @GuardedBy("this") private boolean sealed = false; @@ -38,6 +40,17 @@ final class InMemoryDataTreeModification implements DataTreeModification { this.snapshot = Preconditions.checkNotNull(snapshot); this.strategyTree = Preconditions.checkNotNull(resolver).snapshot(); this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode()); + /* + * We could allocate version beforehand, since Version contract + * states two allocated version must be allways different. + * + * Preallocating version simplifies scenarios such as + * chaining of modifications, since version for particular + * node in modification and in data tree (if successfully + * commited) will be same and will not change. + * + */ + this.version = snapshot.getRootNode().getSubtreeVersion().next(); } ModifiedNode getRootModification() { @@ -49,13 +62,13 @@ final class InMemoryDataTreeModification implements DataTreeModification { } @Override - public synchronized void write(final InstanceIdentifier path, final NormalizedNode value) { + public synchronized void write(final YangInstanceIdentifier path, final NormalizedNode value) { checkSealed(); resolveModificationFor(path).write(value); } @Override - public synchronized void merge(final InstanceIdentifier path, final NormalizedNode data) { + public synchronized void merge(final YangInstanceIdentifier path, final NormalizedNode data) { checkSealed(); mergeImpl(resolveModificationFor(path),data); } @@ -74,20 +87,20 @@ final class InMemoryDataTreeModification implements DataTreeModification { } @Override - public synchronized void delete(final InstanceIdentifier path) { + public synchronized void delete(final YangInstanceIdentifier path) { checkSealed(); resolveModificationFor(path).delete(); } @Override - public synchronized Optional> readNode(final InstanceIdentifier path) { + public synchronized Optional> readNode(final YangInstanceIdentifier path) { /* * Walk the tree from the top, looking for the first node between root and * the requested path which has been modified. If no such node exists, * we use the node itself. */ - final Entry entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE); - final InstanceIdentifier key = entry.getKey(); + final Entry entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE); + final YangInstanceIdentifier key = entry.getKey(); final ModifiedNode mod = entry.getValue(); final Optional result = resolveSnapshot(key, mod); @@ -99,7 +112,7 @@ final class InMemoryDataTreeModification implements DataTreeModification { } } - private Optional resolveSnapshot(final InstanceIdentifier path, + private Optional resolveSnapshot(final YangInstanceIdentifier path, final ModifiedNode modification) { final Optional> potentialSnapshot = modification.getSnapshotCache(); if(potentialSnapshot.isPresent()) { @@ -108,14 +121,14 @@ final class InMemoryDataTreeModification implements DataTreeModification { try { return resolveModificationStrategy(path).apply(modification, modification.getOriginal(), - snapshot.getRootNode().getSubtreeVersion().next()); + version); } catch (Exception e) { LOG.error("Could not create snapshot for {}:{}", path,modification,e); throw e; } } - private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) { + private ModificationApplyOperation resolveModificationStrategy(final YangInstanceIdentifier path) { LOG.trace("Resolving modification apply strategy for {}", path); if(rootNode.getType() == ModificationType.UNMODIFIED) { strategyTree.upgradeIfPossible(); @@ -124,7 +137,7 @@ final class InMemoryDataTreeModification implements DataTreeModification { return TreeNodeUtils.findNodeChecked(strategyTree, path); } - private OperationWithModification resolveModificationFor(final InstanceIdentifier path) { + private OperationWithModification resolveModificationFor(final YangInstanceIdentifier path) { ModifiedNode modification = rootNode; // We ensure strategy is present. ModificationApplyOperation operation = resolveModificationStrategy(path); @@ -160,22 +173,17 @@ final class InMemoryDataTreeModification implements DataTreeModification { } /* - * FIXME: Add advanced transaction chaining for modification of not rebased - * modification. - * - * Current computation of tempRoot may yeld incorrect subtree versions - * if there are multiple concurrent transactions, which may break - * versioning preconditions for modification of previously occured write, - * directly nested under parent node, since node version is derived from - * subtree version. - * - * For deeper nodes subtree version is derived from their respective metadata - * nodes, so this incorrect root subtree version is not affecting us. + * We will use preallocated version, this means returned snapshot will + * have same version each time this method is called. */ TreeNode originalSnapshotRoot = snapshot.getRootNode(); - Optional tempRoot = strategyTree.apply(rootNode, Optional.of(originalSnapshotRoot), originalSnapshotRoot.getSubtreeVersion().next()); + Optional tempRoot = strategyTree.apply(rootNode, Optional.of(originalSnapshotRoot), version); InMemoryDataTreeSnapshot tempTree = new InMemoryDataTreeSnapshot(snapshot.getSchemaContext(), tempRoot.get(), strategyTree); return tempTree.newModification(); } + + Version getVersion() { + return version; + } }