X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fdom%2Fstore%2Fimpl%2Ftree%2Fdata%2FNormalizedNodeContainerModificationStrategy.java;h=1d10ab6ea5a971dfc3e4a160949fd6f5c17fd30b;hp=7ab840e0e05f760623d5eb29ead101db59a4b8d8;hb=1dc26e34f10b751e09c24b4ced676c64b19fa002;hpb=23e677d8d6a8237f5b4d7f1526ee3bcadaada19e diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java index 7ab840e0e0..1d10ab6ea5 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java @@ -11,11 +11,14 @@ import static com.google.common.base.Preconditions.checkArgument; import java.util.Map; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException; import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ListEntryModificationStrategy; import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafSetEntryModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.MutableTreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; @@ -42,7 +45,7 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; -import com.google.common.primitives.UnsignedLong; +import com.google.common.collect.Iterables; abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation { @@ -53,18 +56,18 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp } @Override - public void verifyStructure(final NodeModification modification) throws IllegalArgumentException { - if (modification.getModificationType() == ModificationType.WRITE) { + public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException { + if (modification.getType() == ModificationType.WRITE) { } - for (NodeModification childModification : modification.getModifications()) { + for (ModifiedNode childModification : modification.getChildren()) { resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification); } } @Override protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { + final Optional current) throws DataValidationFailedException { // FIXME: Implement proper write check for replacement of node container // prerequisite is to have transaction chain available for clients // otherwise this will break chained writes to same node. @@ -90,94 +93,100 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp } @Override - protected StoreMetadataNode applyWrite(final NodeModification modification, - final Optional currentMeta, final UnsignedLong subtreeVersion) { + protected TreeNode applyWrite(final ModifiedNode modification, + final Optional currentMeta, final Version version) { + final NormalizedNode newValue = modification.getWrittenValue(); + final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version); - NormalizedNode newValue = modification.getWrittenValue(); - - final UnsignedLong nodeVersion; - if (currentMeta.isPresent()) { - nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion()); - } else { - nodeVersion = subtreeVersion; - } - - final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion); - if (!modification.hasAdditionalModifications()) { + if (Iterables.isEmpty(modification.getChildren())) { return newValueMeta; } - @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue); - StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(nodeVersion, dataBuilder) // - .setSubtreeVersion(subtreeVersion); - - return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion); - } - - @Override - protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, - final UnsignedLong subtreeVersion) { - // For Node Containers - merge is same as subtree change - we only replace children. - return applySubtreeChange(modification, currentMeta, subtreeVersion); - } - - @Override - public StoreMetadataNode applySubtreeChange(final NodeModification modification, - final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { - // Bump subtree version to its new target - final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion()); + /* + * This is where things get interesting. The user has performed a write and + * then she applied some more modifications to it. So we need to make sense + * of that an apply the operations on top of the written value. We could have + * done it during the write, but this operation is potentially expensive, so + * we have left it out of the fast path. + * + * As it turns out, once we materialize the written data, we can share the + * code path with the subtree change. So let's create an unsealed TreeNode + * and run the common parts on it -- which end with the node being sealed. + */ + final MutableTreeNode mutable = newValueMeta.mutable(); + mutable.setSubtreeVersion(version); @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData()); - StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(dataBuilder, currentMeta) - .setIdentifier(modification.getIdentifier()) - .setSubtreeVersion(updatedSubtreeVersion); + final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue); - return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion); + return mutateChildren(mutable, dataBuilder, version, modification.getChildren()); } - private StoreMetadataNode mutateChildren(final Iterable modifications, final StoreMetadataNode meta, - final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data, + final Version nodeVersion, final Iterable modifications) { - for (NodeModification mod : modifications) { + for (ModifiedNode mod : modifications) { final PathArgument id = mod.getIdentifier(); - final Optional cm = meta.getChild(id); + final Optional cm = meta.getChild(id); - Optional result = resolveChildOperation(id).apply(mod, cm, nodeVersion); + Optional result = resolveChildOperation(id).apply(mod, cm, nodeVersion); if (result.isPresent()) { - builder.add(result.get()); + final TreeNode tn = result.get(); + meta.addChild(tn); + data.addChild(tn.getData()); } else { - builder.remove(id); + meta.removeChild(id); + data.removeChild(id); } } - return builder.build(); + meta.setData(data.build()); + return meta.seal(); + } + + @Override + protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, + final Version version) { + // For Node Containers - merge is same as subtree change - we only replace children. + return applySubtreeChange(modification, currentMeta, version); } @Override - protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction."); - checkChildPreconditions(path,modification,current); + public TreeNode applySubtreeChange(final ModifiedNode modification, + final TreeNode currentMeta, final Version version) { + final MutableTreeNode newMeta = currentMeta.mutable(); + newMeta.setSubtreeVersion(version); + + @SuppressWarnings("rawtypes") + NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData()); + + return mutateChildren(newMeta, dataBuilder, version, modification.getChildren()); + } + @Override + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataValidationFailedException { + checkConflicting(path, current.isPresent(), "Node was deleted by other transaction."); + checkChildPreconditions(path, modification, current); } - private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { - StoreMetadataNode currentMeta = current.get(); - for (NodeModification childMod : modification.getModifications()) { - PathArgument childId = childMod.getIdentifier(); - Optional childMeta = currentMeta.getChild(childId); - InstanceIdentifier childPath = StoreUtils.append(path, childId); - resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta); + private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataValidationFailedException { + final TreeNode currentMeta = current.get(); + for (NodeModification childMod : modification.getChildren()) { + final PathArgument childId = childMod.getIdentifier(); + final Optional childMeta = currentMeta.getChild(childId); + + InstanceIdentifier childPath = path.node(childId); + resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta); } } @Override protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { + final Optional current) throws DataValidationFailedException { if(current.isPresent()) { - checkChildPreconditions(path,modification,current); + checkChildPreconditions(path, modification,current); } } @@ -325,4 +334,4 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]"; } } -} \ No newline at end of file +}