X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fdom%2Fstore%2Fimpl%2FSchemaAwareApplyOperation.java;h=2af522ea861791fcae324f2f5761b258d93b8845;hb=refs%2Fchanges%2F91%2F6891%2F3;hp=4bb5aed20c72d9a8424063818cf0c84e31630b47;hpb=d1243dc6da239191adb49fe6c78a933553af1939;p=controller.git diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java index 4bb5aed20c..2af522ea86 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java @@ -20,6 +20,7 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; @@ -141,55 +142,52 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper protected abstract void verifyWritenStructure(NormalizedNode writenValue); @Override - public boolean isApplicable(final NodeModification modification, final Optional current) { + public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { switch (modification.getModificationType()) { case DELETE: - return isDeleteApplicable(modification, current); + checkDeleteApplicable(modification, current); case SUBTREE_MODIFIED: - return isSubtreeModificationApplicable(modification, current); + checkSubtreeModificationApplicable(path,modification, current); + return; case WRITE: - return isWriteApplicable(modification, current); + checkWriteApplicable(path,modification, current); + return; case MERGE: - return isMergeApplicable(modification,current); + checkMergeApplicable(path,modification,current); + return; case UNMODIFIED: - return true; + return; default: - return false; + throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported."); } + } - private boolean isMergeApplicable(final NodeModification modification, final Optional current) { + protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { - return isNotConflicting(original.get(), current.get()); - } else if (current.isPresent()) { - return true; + checkNotConflicting(path,original.get(), current.get()); } - return true; } - protected boolean isWriteApplicable(final NodeModification modification, final Optional current) { + protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { - return isNotConflicting(original.get(), current.get()); - } else if (current.isPresent()) { - return false; + checkNotConflicting(path,original.get(), current.get()); + } else if(original.isPresent()) { + throw new DataPreconditionFailedException(path,"Node was deleted by other transaction."); } - return true; - } - protected final boolean isNotConflicting(final StoreMetadataNode original, final StoreMetadataNode current) { - return original.getNodeVersion().equals(current.getNodeVersion()) - && original.getSubtreeVersion().equals(current.getSubtreeVersion()); + protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException { + checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction."); + checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction"); } - protected abstract boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current); + protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException; - private boolean isDeleteApplicable(final NodeModification modification, final Optional current) { - // FiXME: Add delete conflict detection. - return true; + private void checkDeleteApplicable(final NodeModification modification, final Optional current) { } @Override @@ -271,9 +269,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } @Override - protected boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current) { - return false; + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); } } @@ -312,6 +310,14 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } } + @Override + protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + // 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. + } + @SuppressWarnings("rawtypes") @Override protected void verifyWritenStructure(final NormalizedNode writenValue) { @@ -392,19 +398,29 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } @Override - protected boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current) { - if (false == current.isPresent()) { - return false; - } - boolean result = true; + 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); + + } + + 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); - result &= resolveChildOperation(childId).isApplicable(childMod, childMeta); + InstanceIdentifier childPath = StoreUtils.append(path, childId); + resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta); + } + } + + @Override + protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + if(current.isPresent()) { + checkChildPreconditions(path,modification,current); } - return result; } @SuppressWarnings("rawtypes") @@ -497,8 +513,6 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) { super(createAugmentProxy(schema,resolved), AugmentationNode.class); - // FIXME: Use resolved children instead of unresolved. - } @Override @@ -647,9 +661,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } @Override - protected boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current) { - return false; + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); } } @@ -726,4 +740,11 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper return new AugmentationSchemaProxy(schema, realChildSchemas); } + public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException { + if(!condition) { + throw new DataPreconditionFailedException(path, message); + } + return condition; + } + }