From: Tom Pantelis Date: Wed, 13 Aug 2014 12:12:10 +0000 (+0000) Subject: Merge "Add exists method on DOMStoreReadTransaction and DOMDataReadTransaction" X-Git-Tag: release/helium~299 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=a3ff4b68093e6d675a92159e0efa2525af32d644;hp=83e1c1d691f0b37b751b7ee07d9dc91c791d558e Merge "Add exists method on DOMStoreReadTransaction and DOMDataReadTransaction" --- diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java index 5ced7bae9f..8fbc118a16 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java @@ -7,22 +7,19 @@ */ package org.opendaylight.controller.md.sal.binding.impl; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ExecutionException; - import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Optional; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class AbstractReadWriteTransaction extends AbstractWriteTransaction { @@ -50,15 +47,15 @@ public class AbstractReadWriteTransaction extends AbstractWriteTransaction> d; + final Boolean exists; try { - d = getDelegate().read(store, currentPath).get(); - } catch (InterruptedException | ExecutionException e) { + exists = getDelegate().exists(store, currentPath).checkedGet(); + } catch (ReadFailedException e) { LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e); throw new IllegalStateException("Failed to read pre-existing data", e); } - if (!d.isPresent() && iterator.hasNext()) { + if (!exists && iterator.hasNext()) { getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg)); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java new file mode 100644 index 0000000000..f91e356b8e --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java @@ -0,0 +1,72 @@ +package org.opendaylight.controller.md.sal.binding.impl.test; + +import org.junit.Test; +import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker; +import org.opendaylight.controller.md.sal.binding.test.AbstractSchemaAwareTest; +import org.opendaylight.controller.md.sal.binding.test.DataBrokerTestCustomizer; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +import java.util.concurrent.ExecutionException; + +import static junit.framework.TestCase.assertNotNull; + +public class ForwardedBackwardsCompatibleDataBrokerTest extends + AbstractSchemaAwareTest { + + private DataBrokerTestCustomizer testCustomizer; + private ForwardedBackwardsCompatibleDataBroker dataBroker; + private DOMDataBroker domBroker; + + private static final InstanceIdentifier TOP_PATH = InstanceIdentifier.create(Top.class); + private static final TopLevelListKey TOP_LIST_KEY = new TopLevelListKey("foo"); + private static final InstanceIdentifier NODE_PATH = TOP_PATH.child(TopLevelList.class, TOP_LIST_KEY); + private static final TopLevelList NODE = new TopLevelListBuilder().setKey(TOP_LIST_KEY).build(); + + protected DataBrokerTestCustomizer createDataBrokerTestCustomizer() { + return new DataBrokerTestCustomizer(); + } + + @Override + protected void setupWithSchema(final SchemaContext context) { + testCustomizer = createDataBrokerTestCustomizer(); + + domBroker = testCustomizer.createDOMDataBroker(); + dataBroker = testCustomizer.createBackwardsCompatibleDataBroker(); + testCustomizer.updateSchema(context); + } + + + /** + * The purpose of this test is to exercise the backwards compatible broker + *

+ * This test tries to execute the code which ensures that the parents + * for a given node get automatically created. + * + * @see org.opendaylight.controller.md.sal.binding.impl.AbstractReadWriteTransaction#ensureParentsByMerge(org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType, org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, org.opendaylight.yangtools.yang.binding.InstanceIdentifier) + */ + @Test + public void test() throws InterruptedException, ExecutionException { + DataModificationTransaction writeTx = + dataBroker.beginTransaction(); + + writeTx.putOperationalData(NODE_PATH, NODE); + + writeTx.commit(); + + // TOP_PATH should exist as it is the parent of NODE_PATH + DataObject object = dataBroker.readOperationalData(TOP_PATH); + + assertNotNull(object); + + } + + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java index 666c819c82..60eec55ca5 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.md.sal.binding.test; import javassist.ClassPool; import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker; import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; @@ -71,6 +72,11 @@ public class DataBrokerTestCustomizer { return new ForwardedBindingDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService()); } + public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() { + return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService(), MoreExecutors.sameThreadExecutor()); + } + + private SchemaService getSchemaService() { return schemaService; } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java index 33ac9f6ca1..bdd66d3aba 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java @@ -6579,6 +6579,933 @@ public final class ShardTransactionMessages { // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.MergeDataReply) } + public interface DataExistsOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + boolean hasInstanceIdentifierPathArguments(); + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierPathArguments(); + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierPathArgumentsOrBuilder(); + } + /** + * Protobuf type {@code org.opendaylight.controller.mdsal.DataExists} + */ + public static final class DataExists extends + com.google.protobuf.GeneratedMessage + implements DataExistsOrBuilder { + // Use DataExists.newBuilder() to construct. + private DataExists(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private DataExists(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final DataExists defaultInstance; + public static DataExists getDefaultInstance() { + return defaultInstance; + } + + public DataExists getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private DataExists( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder subBuilder = null; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + subBuilder = instanceIdentifierPathArguments_.toBuilder(); + } + instanceIdentifierPathArguments_ = input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(instanceIdentifierPathArguments_); + instanceIdentifierPathArguments_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000001; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public DataExists parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new DataExists(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + public static final int INSTANCEIDENTIFIERPATHARGUMENTS_FIELD_NUMBER = 1; + private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierPathArguments_; + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public boolean hasInstanceIdentifierPathArguments() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierPathArguments() { + return instanceIdentifierPathArguments_; + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierPathArgumentsOrBuilder() { + return instanceIdentifierPathArguments_; + } + + private void initFields() { + instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance(); + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + if (!hasInstanceIdentifierPathArguments()) { + memoizedIsInitialized = 0; + return false; + } + if (!getInstanceIdentifierPathArguments().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeMessage(1, instanceIdentifierPathArguments_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, instanceIdentifierPathArguments_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.opendaylight.controller.mdsal.DataExists} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.Builder.class); + } + + // Construct using org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getInstanceIdentifierPathArgumentsFieldBuilder(); + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + if (instanceIdentifierPathArgumentsBuilder_ == null) { + instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance(); + } else { + instanceIdentifierPathArgumentsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor; + } + + public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists getDefaultInstanceForType() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.getDefaultInstance(); + } + + public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists build() { + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists buildPartial() { + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists result = new org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + if (instanceIdentifierPathArgumentsBuilder_ == null) { + result.instanceIdentifierPathArguments_ = instanceIdentifierPathArguments_; + } else { + result.instanceIdentifierPathArguments_ = instanceIdentifierPathArgumentsBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists) { + return mergeFrom((org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists other) { + if (other == org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.getDefaultInstance()) return this; + if (other.hasInstanceIdentifierPathArguments()) { + mergeInstanceIdentifierPathArguments(other.getInstanceIdentifierPathArguments()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasInstanceIdentifierPathArguments()) { + + return false; + } + if (!getInstanceIdentifierPathArguments().isInitialized()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> instanceIdentifierPathArgumentsBuilder_; + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public boolean hasInstanceIdentifierPathArguments() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierPathArguments() { + if (instanceIdentifierPathArgumentsBuilder_ == null) { + return instanceIdentifierPathArguments_; + } else { + return instanceIdentifierPathArgumentsBuilder_.getMessage(); + } + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public Builder setInstanceIdentifierPathArguments(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) { + if (instanceIdentifierPathArgumentsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + instanceIdentifierPathArguments_ = value; + onChanged(); + } else { + instanceIdentifierPathArgumentsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public Builder setInstanceIdentifierPathArguments( + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder builderForValue) { + if (instanceIdentifierPathArgumentsBuilder_ == null) { + instanceIdentifierPathArguments_ = builderForValue.build(); + onChanged(); + } else { + instanceIdentifierPathArgumentsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public Builder mergeInstanceIdentifierPathArguments(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) { + if (instanceIdentifierPathArgumentsBuilder_ == null) { + if (((bitField0_ & 0x00000001) == 0x00000001) && + instanceIdentifierPathArguments_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance()) { + instanceIdentifierPathArguments_ = + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.newBuilder(instanceIdentifierPathArguments_).mergeFrom(value).buildPartial(); + } else { + instanceIdentifierPathArguments_ = value; + } + onChanged(); + } else { + instanceIdentifierPathArgumentsBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public Builder clearInstanceIdentifierPathArguments() { + if (instanceIdentifierPathArgumentsBuilder_ == null) { + instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance(); + onChanged(); + } else { + instanceIdentifierPathArgumentsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder getInstanceIdentifierPathArgumentsBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return getInstanceIdentifierPathArgumentsFieldBuilder().getBuilder(); + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierPathArgumentsOrBuilder() { + if (instanceIdentifierPathArgumentsBuilder_ != null) { + return instanceIdentifierPathArgumentsBuilder_.getMessageOrBuilder(); + } else { + return instanceIdentifierPathArguments_; + } + } + /** + * required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> + getInstanceIdentifierPathArgumentsFieldBuilder() { + if (instanceIdentifierPathArgumentsBuilder_ == null) { + instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>( + instanceIdentifierPathArguments_, + getParentForChildren(), + isClean()); + instanceIdentifierPathArguments_ = null; + } + return instanceIdentifierPathArgumentsBuilder_; + } + + // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.DataExists) + } + + static { + defaultInstance = new DataExists(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.DataExists) + } + + public interface DataExistsReplyOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // required bool exists = 1; + /** + * required bool exists = 1; + */ + boolean hasExists(); + /** + * required bool exists = 1; + */ + boolean getExists(); + } + /** + * Protobuf type {@code org.opendaylight.controller.mdsal.DataExistsReply} + */ + public static final class DataExistsReply extends + com.google.protobuf.GeneratedMessage + implements DataExistsReplyOrBuilder { + // Use DataExistsReply.newBuilder() to construct. + private DataExistsReply(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private DataExistsReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final DataExistsReply defaultInstance; + public static DataExistsReply getDefaultInstance() { + return defaultInstance; + } + + public DataExistsReply getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private DataExistsReply( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 8: { + bitField0_ |= 0x00000001; + exists_ = input.readBool(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public DataExistsReply parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new DataExistsReply(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // required bool exists = 1; + public static final int EXISTS_FIELD_NUMBER = 1; + private boolean exists_; + /** + * required bool exists = 1; + */ + public boolean hasExists() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required bool exists = 1; + */ + public boolean getExists() { + return exists_; + } + + private void initFields() { + exists_ = false; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + if (!hasExists()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBool(1, exists_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(1, exists_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.opendaylight.controller.mdsal.DataExistsReply} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReplyOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.Builder.class); + } + + // Construct using org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + exists_ = false; + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor; + } + + public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply getDefaultInstanceForType() { + return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.getDefaultInstance(); + } + + public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply build() { + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply buildPartial() { + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply result = new org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.exists_ = exists_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply) { + return mergeFrom((org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply other) { + if (other == org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.getDefaultInstance()) return this; + if (other.hasExists()) { + setExists(other.getExists()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasExists()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // required bool exists = 1; + private boolean exists_ ; + /** + * required bool exists = 1; + */ + public boolean hasExists() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required bool exists = 1; + */ + public boolean getExists() { + return exists_; + } + /** + * required bool exists = 1; + */ + public Builder setExists(boolean value) { + bitField0_ |= 0x00000001; + exists_ = value; + onChanged(); + return this; + } + /** + * required bool exists = 1; + */ + public Builder clearExists() { + bitField0_ = (bitField0_ & ~0x00000001); + exists_ = false; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.DataExistsReply) + } + + static { + defaultInstance = new DataExistsReply(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.DataExistsReply) + } + private static com.google.protobuf.Descriptors.Descriptor internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor; private static @@ -6649,6 +7576,16 @@ public final class ShardTransactionMessages { private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_org_opendaylight_controller_mdsal_MergeDataReply_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { @@ -6683,10 +7620,13 @@ public final class ShardTransactionMessages { "thArguments\030\001 \002(\01325.org.opendaylight.con" + "troller.mdsal.InstanceIdentifier\022?\n\016norm" + "alizedNode\030\002 \002(\0132\'.org.opendaylight.cont" + - "roller.mdsal.Node\"\020\n\016MergeDataReplyBV\n:o" + - "rg.opendaylight.controller.protobuff.mes" + - "sages.transactionB\030ShardTransactionMessa" + - "ges" + "roller.mdsal.Node\"\020\n\016MergeDataReply\"l\n\nD" + + "ataExists\022^\n\037instanceIdentifierPathArgum" + + "ents\030\001 \002(\01325.org.opendaylight.controller" + + ".mdsal.InstanceIdentifier\"!\n\017DataExistsR" + + "eply\022\016\n\006exists\030\001 \002(\010BV\n:org.opendaylight", + ".controller.protobuff.messages.transacti" + + "onB\030ShardTransactionMessages" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -6777,6 +7717,18 @@ public final class ShardTransactionMessages { com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_org_opendaylight_controller_mdsal_MergeDataReply_descriptor, new java.lang.String[] { }); + internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor = + getDescriptor().getMessageTypes().get(14); + internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor, + new java.lang.String[] { "InstanceIdentifierPathArguments", }); + internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor = + getDescriptor().getMessageTypes().get(15); + internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor, + new java.lang.String[] { "Exists", }); return null; } }; diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto b/opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto index 4177bd7a05..63b75ac430 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto @@ -65,3 +65,11 @@ required Node normalizedNode =2; message MergeDataReply{ } + +message DataExists { + required InstanceIdentifier instanceIdentifierPathArguments = 1; +} + +message DataExistsReply { + required bool exists = 1; +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java index 7a18fca100..1328d466f3 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java @@ -16,6 +16,7 @@ import akka.event.Logging; import akka.event.LoggingAdapter; import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction; import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply; +import org.opendaylight.controller.cluster.datastore.messages.DataExists; import org.opendaylight.controller.cluster.datastore.messages.ReadData; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction; import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain; @@ -44,7 +45,9 @@ public class ShardReadTransaction extends ShardTransaction { @Override public void handleReceive(Object message) throws Exception { if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) { - readData(transaction,ReadData.fromSerializable(message)); + readData(transaction, ReadData.fromSerializable(message)); + } else if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) { + dataExists(transaction, DataExists.fromSerializable(message)); } else { super.handleReceive(message); } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java index 92fb393083..97bb196f9f 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java @@ -16,6 +16,7 @@ import akka.event.Logging; import akka.event.LoggingAdapter; import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction; import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply; +import org.opendaylight.controller.cluster.datastore.messages.DataExists; import org.opendaylight.controller.cluster.datastore.messages.DeleteData; import org.opendaylight.controller.cluster.datastore.messages.MergeData; import org.opendaylight.controller.cluster.datastore.messages.ReadData; @@ -55,6 +56,8 @@ public class ShardReadWriteTransaction extends ShardTransaction { deleteData(transaction,DeleteData.fromSerizalizable(message)); } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) { readyTransaction(transaction,new ReadyTransaction()); + } else if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) { + dataExists(transaction, DataExists.fromSerializable(message)); }else { super.handleReceive(message); } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java index 1ffe5ca402..360a10722c 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java @@ -14,9 +14,11 @@ import akka.event.Logging; import akka.event.LoggingAdapter; import akka.japi.Creator; import com.google.common.base.Optional; -import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.CheckedFuture; import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageException; import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction; +import org.opendaylight.controller.cluster.datastore.messages.DataExists; +import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply; import org.opendaylight.controller.cluster.datastore.messages.DeleteData; import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply; import org.opendaylight.controller.cluster.datastore.messages.MergeData; @@ -183,28 +185,38 @@ public abstract class ShardTransaction extends AbstractUntypedActor { final ActorRef sender = getSender(); final ActorRef self = getSelf(); final YangInstanceIdentifier path = message.getPath(); - final ListenableFuture>> future = - transaction.read(path); + final CheckedFuture>, ReadFailedException> future = + transaction.read(path); - future.addListener(new Runnable() { + future.addListener(new Runnable() { @Override public void run() { try { - Optional> optional = future.get(); + Optional> optional = future.checkedGet(); if (optional.isPresent()) { sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self); } else { sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self); } } catch (Exception e) { - sender.tell(new akka.actor.Status.Failure(new ReadFailedException( "An Exception occurred when reading data from path : " - + path.toString(),e)),self); + sender.tell(new akka.actor.Status.Failure(e),self); } } }, getContext().dispatcher()); } + protected void dataExists(DOMStoreReadTransaction transaction, DataExists message) { + final YangInstanceIdentifier path = message.getPath(); + + try { + Boolean exists = transaction.exists(path).checkedGet(); + getSender().tell(new DataExistsReply(exists).toSerializable(), getSelf()); + } catch (ReadFailedException e) { + getSender().tell(new akka.actor.Status.Failure(e),getSelf()); + } + + } protected void writeData(DOMStoreWriteTransaction transaction, WriteData message) { modification.addModification( diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java index 5f9f1f83c4..95862ae9d9 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java @@ -23,6 +23,8 @@ import org.opendaylight.controller.cluster.datastore.identifiers.TransactionIden import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction; import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction; import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply; +import org.opendaylight.controller.cluster.datastore.messages.DataExists; +import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply; import org.opendaylight.controller.cluster.datastore.messages.DeleteData; import org.opendaylight.controller.cluster.datastore.messages.MergeData; import org.opendaylight.controller.cluster.datastore.messages.ReadData; @@ -113,6 +115,15 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction { return transactionContext(path).readData(path); } + @Override public CheckedFuture exists( + YangInstanceIdentifier path) { + LOG.debug("txn {} exists {}", identifier, path); + + createTransactionIfMissing(actorContext, path); + + return transactionContext(path).dataExists(path); + } + @Override public void write(YangInstanceIdentifier path, NormalizedNode data) { @@ -243,13 +254,15 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction { final YangInstanceIdentifier path); void writeData(YangInstanceIdentifier path, NormalizedNode data); + + CheckedFuture dataExists(YangInstanceIdentifier path); } - private class TransactionContextImpl implements TransactionContext{ + private class TransactionContextImpl implements TransactionContext { private final String shardName; private final String actorPath; - private final ActorSelection actor; + private final ActorSelection actor; private TransactionContextImpl(String shardName, String actorPath, @@ -267,7 +280,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction { return actor; } - @Override public String getResolvedCohortPath(String cohortPath){ + @Override public String getResolvedCohortPath(String cohortPath) { return actorContext.resolvePath(actorPath, cohortPath); } @@ -288,38 +301,76 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction { getActor().tell(new DeleteData(path).toSerializable(), null); } - @Override public void mergeData(YangInstanceIdentifier path, NormalizedNode data){ - getActor().tell(new MergeData(path, data, schemaContext).toSerializable(), null); + @Override public void mergeData(YangInstanceIdentifier path, + NormalizedNode data) { + getActor() + .tell(new MergeData(path, data, schemaContext).toSerializable(), + null); } - @Override public CheckedFuture>, ReadFailedException> readData( - final YangInstanceIdentifier path) { - - Callable>> call = new Callable>>() { + @Override + public CheckedFuture>, ReadFailedException> readData( + final YangInstanceIdentifier path) { - @Override public Optional> call() throws Exception { - Object response = actorContext - .executeRemoteOperation(getActor(), new ReadData(path).toSerializable(), - ActorContext.ASK_DURATION); - if(response.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)){ - ReadDataReply reply = ReadDataReply.fromSerializable(schemaContext,path, response); - if(reply.getNormalizedNode() == null){ - return Optional.absent(); + Callable>> call = + new Callable>>() { + + @Override public Optional> call() + throws Exception { + Object response = actorContext + .executeRemoteOperation(getActor(), + new ReadData(path).toSerializable(), + ActorContext.ASK_DURATION); + if (response.getClass() + .equals(ReadDataReply.SERIALIZABLE_CLASS)) { + ReadDataReply reply = ReadDataReply + .fromSerializable(schemaContext, path, + response); + if (reply.getNormalizedNode() == null) { + return Optional.absent(); + } + return Optional.>of( + reply.getNormalizedNode()); } - return Optional.>of(reply.getNormalizedNode()); - } - return Optional.absent(); - } - }; + throw new ReadFailedException("Read Failed " + path); + } + }; - return MappingCheckedFuture.create(executor.submit(call), ReadFailedException.MAPPER); + return MappingCheckedFuture + .create(executor.submit(call), ReadFailedException.MAPPER); } - @Override public void writeData(YangInstanceIdentifier path, NormalizedNode data) { - getActor().tell(new WriteData(path, data, schemaContext).toSerializable(), null); + @Override public void writeData(YangInstanceIdentifier path, + NormalizedNode data) { + getActor() + .tell(new WriteData(path, data, schemaContext).toSerializable(), + null); } + @Override public CheckedFuture dataExists( + final YangInstanceIdentifier path) { + + Callable call = new Callable() { + + @Override public Boolean call() throws Exception { + Object o = actorContext.executeRemoteOperation(getActor(), + new DataExists(path).toSerializable(), + ActorContext.ASK_DURATION + ); + + + if (DataExistsReply.SERIALIZABLE_CLASS + .equals(o.getClass())) { + return DataExistsReply.fromSerializable(o).exists(); + } + + throw new ReadFailedException("Exists Failed " + path); + } + }; + return MappingCheckedFuture + .create(executor.submit(call), ReadFailedException.MAPPER); + } } private class NoOpTransactionContext implements TransactionContext { @@ -374,6 +425,15 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction { NormalizedNode data) { LOG.warn("txn {} writeData called path = {}", identifier, path); } + + @Override public CheckedFuture dataExists( + YangInstanceIdentifier path) { + LOG.warn("txn {} dataExists called path = {}", identifier, path); + + // Returning false instead of an exception to keep this aligned with + // read + return Futures.immediateCheckedFuture(false); + } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExists.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExists.java new file mode 100644 index 0000000000..d52daabd84 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExists.java @@ -0,0 +1,40 @@ +/* + * 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.cluster.datastore.messages; + +import org.opendaylight.controller.cluster.datastore.util.InstanceIdentifierUtils; +import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; + +public class DataExists implements SerializableMessage{ + + public static final Class SERIALIZABLE_CLASS = ShardTransactionMessages.DataExists.class; + + private final YangInstanceIdentifier path; + + public DataExists(YangInstanceIdentifier path) { + this.path = path; + } + + public YangInstanceIdentifier getPath() { + return path; + } + + @Override public Object toSerializable() { + return ShardTransactionMessages.DataExists.newBuilder() + .setInstanceIdentifierPathArguments( + InstanceIdentifierUtils.toSerializable(path)).build(); + } + + public static DataExists fromSerializable(Object serializable){ + ShardTransactionMessages.DataExists o = (ShardTransactionMessages.DataExists) serializable; + return new DataExists(InstanceIdentifierUtils.fromSerializable(o.getInstanceIdentifierPathArguments())); + } + +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExistsReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExistsReply.java new file mode 100644 index 0000000000..04fafa10e2 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExistsReply.java @@ -0,0 +1,38 @@ +/* + * 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.cluster.datastore.messages; + +import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages; + +public class DataExistsReply implements SerializableMessage{ + + + public static final Class SERIALIZABLE_CLASS = ShardTransactionMessages.DataExistsReply.class; + + private final boolean exists; + + public DataExistsReply(boolean exists) { + this.exists = exists; + } + + public boolean exists() { + return exists; + } + + @Override public Object toSerializable() { + return ShardTransactionMessages.DataExistsReply.newBuilder() + .setExists(exists).build(); + } + + public static DataExistsReply fromSerializable(Object serializable){ + ShardTransactionMessages.DataExistsReply o = (ShardTransactionMessages.DataExistsReply) serializable; + return new DataExistsReply(o.getExists()); + } + +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionFailureTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionFailureTest.java index 0f9e771ab4..02ceee82e0 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionFailureTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionFailureTest.java @@ -122,6 +122,41 @@ public class ShardTransactionFailureTest extends AbstractActorTest { Await.result(future, Duration.Zero()); + } + + @Test(expected = ReadFailedException.class) + public void testNegativeExistsWithReadWriteOnlyTransactionClosed() + throws Throwable { + + final ActorRef shard = + getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP)); + final Props props = + ShardTransaction.props(store.newReadWriteTransaction(), shard, + TestModel.createTestContext()); + + final TestActorRef subject = TestActorRef + .create(getSystem(), props, + "testNegativeExistsWithReadWriteOnlyTransactionClosed"); + + ShardTransactionMessages.DataExists dataExists = + ShardTransactionMessages.DataExists.newBuilder() + .setInstanceIdentifierPathArguments( + NormalizedNodeMessages.InstanceIdentifier.newBuilder() + .build() + ).build(); + + Future future = + akka.pattern.Patterns.ask(subject, dataExists, 3000); + assertTrue(future.isCompleted()); + Await.result(future, Duration.Zero()); + + ((ShardReadWriteTransaction) subject.underlyingActor()) + .forUnitTestOnlyExplicitTransactionClose(); + + future = akka.pattern.Patterns.ask(subject, dataExists, 3000); + Await.result(future, Duration.Zero()); + + } @Test(expected = IllegalStateException.class) diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java index a2273f61f8..78895b2366 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java @@ -13,6 +13,8 @@ import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageEx import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier; import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction; import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply; +import org.opendaylight.controller.cluster.datastore.messages.DataExists; +import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply; import org.opendaylight.controller.cluster.datastore.messages.DeleteData; import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply; import org.opendaylight.controller.cluster.datastore.messages.MergeData; @@ -142,6 +144,90 @@ public class ShardTransactionTest extends AbstractActorTest { }}; } + @Test + public void testOnReceiveDataExistsPositive() throws Exception { + new JavaTestKit(getSystem()) {{ + final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP)); + final Props props = + ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext); + final ActorRef subject = getSystem().actorOf(props, "testDataExistsPositive"); + + new Within(duration("1 seconds")) { + @Override + protected void run() { + + subject.tell( + new DataExists(YangInstanceIdentifier.builder().build()).toSerializable(), + getRef()); + + final String out = new ExpectMsg(duration("1 seconds"), "match hint") { + // do not put code outside this method, will run afterwards + @Override + protected String match(Object in) { + if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) { + if (DataExistsReply.fromSerializable(in) + .exists()) { + return "match"; + } + return null; + } else { + throw noMatch(); + } + } + }.get(); // this extracts the received message + + assertEquals("match", out); + + expectNoMsg(); + } + + + }; + }}; + } + + @Test + public void testOnReceiveDataExistsNegative() throws Exception { + new JavaTestKit(getSystem()) {{ + final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP)); + final Props props = + ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext); + final ActorRef subject = getSystem().actorOf(props, "testDataExistsNegative"); + + new Within(duration("1 seconds")) { + @Override + protected void run() { + + subject.tell( + new DataExists(TestModel.TEST_PATH).toSerializable(), + getRef()); + + final String out = new ExpectMsg(duration("1 seconds"), "match hint") { + // do not put code outside this method, will run afterwards + @Override + protected String match(Object in) { + if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) { + if (!DataExistsReply.fromSerializable(in) + .exists()) { + return "match"; + } + return null; + } else { + throw noMatch(); + } + } + }.get(); // this extracts the received message + + assertEquals("match", out); + + expectNoMsg(); + } + + + }; + }}; + } + private void assertModification(final ActorRef subject, final Class modificationType) { new JavaTestKit(getSystem()) {{ diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java index 0cd029c2ff..62052f38ab 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java @@ -2,20 +2,19 @@ package org.opendaylight.controller.cluster.datastore; import akka.actor.ActorRef; import akka.actor.Props; - import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; - import junit.framework.Assert; - import org.junit.After; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.cluster.datastore.exceptions.PrimaryNotFoundException; import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException; import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction; +import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply; import org.opendaylight.controller.cluster.datastore.messages.DeleteData; import org.opendaylight.controller.cluster.datastore.messages.MergeData; import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound; @@ -30,6 +29,7 @@ import org.opendaylight.controller.cluster.datastore.utils.MockActorContext; import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper; import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration; import org.opendaylight.controller.md.cluster.datastore.model.TestModel; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.CreateTransactionReply; import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -81,6 +81,10 @@ public class TransactionProxyTest extends AbstractActorTest { TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext()); + actorContext.setExecuteRemoteOperationResponse( + new ReadDataReply(TestModel.createTestContext(), null) + .toSerializable()); + ListenableFuture>> read = transactionProxy.read(TestModel.TEST_PATH); @@ -99,7 +103,7 @@ public class TransactionProxyTest extends AbstractActorTest { } @Test - public void testReadWhenANullIsReturned() throws Exception { + public void testExists() throws Exception { final Props props = Props.create(DoNothingActor.class); final ActorRef actorRef = getSystem().actorOf(props); @@ -108,26 +112,57 @@ public class TransactionProxyTest extends AbstractActorTest { actorContext.setExecuteShardOperationResponse(createTransactionReply(actorRef)); actorContext.setExecuteRemoteOperationResponse("message"); + TransactionProxy transactionProxy = new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext()); - ListenableFuture>> read = - transactionProxy.read(TestModel.TEST_PATH); + actorContext.setExecuteRemoteOperationResponse(new DataExistsReply(false).toSerializable()); - Optional> normalizedNodeOptional = read.get(); + CheckedFuture exists = + transactionProxy.exists(TestModel.TEST_PATH); - Assert.assertFalse(normalizedNodeOptional.isPresent()); + Assert.assertFalse(exists.checkedGet()); - actorContext.setExecuteRemoteOperationResponse(new ReadDataReply( - TestModel.createTestContext(), null).toSerializable()); + actorContext.setExecuteRemoteOperationResponse(new DataExistsReply(true).toSerializable()); - read = transactionProxy.read(TestModel.TEST_PATH); + exists = transactionProxy.exists(TestModel.TEST_PATH); - normalizedNodeOptional = read.get(); + Assert.assertTrue(exists.checkedGet()); - Assert.assertFalse(normalizedNodeOptional.isPresent()); + actorContext.setExecuteRemoteOperationResponse("bad message"); + + exists = transactionProxy.exists(TestModel.TEST_PATH); + + try { + exists.checkedGet(); + fail(); + } catch(ReadFailedException e){ + } + + } + + @Test(expected = ReadFailedException.class) + public void testReadWhenAnInvalidMessageIsSentInReply() throws Exception { + final Props props = Props.create(DoNothingActor.class); + final ActorRef actorRef = getSystem().actorOf(props); + + final MockActorContext actorContext = new MockActorContext(this.getSystem()); + actorContext.setExecuteLocalOperationResponse(createPrimaryFound(actorRef)); + actorContext.setExecuteShardOperationResponse(createTransactionReply(actorRef)); + actorContext.setExecuteRemoteOperationResponse("message"); + + TransactionProxy transactionProxy = + new TransactionProxy(actorContext, + TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext()); + + + + CheckedFuture>, ReadFailedException> + read = transactionProxy.read(TestModel.TEST_PATH); + + read.checkedGet(); } @Test diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadTransaction.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadTransaction.java index fc251c8445..9b70f0c4d7 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadTransaction.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadTransaction.java @@ -47,4 +47,22 @@ public interface DOMDataReadTransaction extends AsyncReadTransaction>, ReadFailedException> read( LogicalDatastoreType store, YangInstanceIdentifier path); + + /** + * Checks if data is available in the logical data store located at provided path + * + * @param path + * Path which uniquely identifies subtree which client want to + * check existence of + * @return a CheckFuture containing the result of the check. + *
    + *
  • If the data at the supplied path exists, the Future returns a Boolean + * whose value is true, false otherwise
  • + *
  • If checking for the data fails, the Future will fail with a + * {@link ReadFailedException} or an exception derived from ReadFailedException.
  • + *
+ */ + CheckedFuture exists( + LogicalDatastoreType store, YangInstanceIdentifier path); + } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadOnlyTransaction.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadOnlyTransaction.java index b4562cf2ec..5e2a417d28 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadOnlyTransaction.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadOnlyTransaction.java @@ -40,6 +40,12 @@ class DOMForwardedReadOnlyTransaction extends return getSubtransaction(store).read(path); } + @Override public CheckedFuture exists( + LogicalDatastoreType store, + YangInstanceIdentifier path) { + return getSubtransaction(store).exists(path); + } + @Override public void close() { closeSubtransactions(); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadWriteTransaction.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadWriteTransaction.java index 74a4c52e36..67351ec945 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadWriteTransaction.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadWriteTransaction.java @@ -50,4 +50,10 @@ class DOMForwardedReadWriteTransaction extends DOMForwardedWriteTransaction exists( + LogicalDatastoreType store, + YangInstanceIdentifier path) { + return getSubtransaction(store).exists(path); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java index 5bd8a7bc02..fb72b5a99a 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java @@ -15,13 +15,6 @@ import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nullable; - import org.opendaylight.controller.md.sal.common.api.RegistrationListener; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; @@ -78,6 +71,12 @@ import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; + public class BackwardsCompatibleMountPoint implements MountProvisionInstance, SchemaContextProvider, SchemaService { private final DataProviderService dataReader; @@ -405,6 +404,16 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc final Optional> normalizedNodeOptional = Optional.>fromNullable(normalized.getValue()); return Futures.immediateCheckedFuture(normalizedNodeOptional); } + + @Override public CheckedFuture exists(LogicalDatastoreType store, + YangInstanceIdentifier path) { + + try { + return Futures.immediateCheckedFuture(read(store, path).get().isPresent()); + } catch (InterruptedException | ExecutionException e) { + return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e)); + } + } } @VisibleForTesting @@ -518,6 +527,16 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc return new BackwardsCompatibleReadTransaction(dataReader, dataNormalizer).read(store, path); } + @Override public CheckedFuture exists(LogicalDatastoreType store, + YangInstanceIdentifier path) { + + try { + return Futures.immediateCheckedFuture(read(store, path).get().isPresent()); + } catch (InterruptedException | ExecutionException e) { + return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e)); + } + } + @Override public boolean cancel() { return delegateWriteTx.cancel(); diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreReadTransaction.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreReadTransaction.java index 84d09c7cb0..719a6f0499 100644 --- a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreReadTransaction.java +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreReadTransaction.java @@ -34,4 +34,20 @@ public interface DOMStoreReadTransaction extends DOMStoreTransaction { * */ CheckedFuture>, ReadFailedException> read(YangInstanceIdentifier path); + + /** + * Checks if data is available in the logical data store located at provided path + * + * @param path + * Path which uniquely identifies subtree which client want to + * check existence of + * @return a CheckFuture containing the result of the check. + *
    + *
  • If the data at the supplied path exists, the Future returns a Boolean + * whose value is true, false otherwise
  • + *
  • If checking for the data fails, the Future will fail with a + * {@link ReadFailedException} or an exception derived from ReadFailedException.
  • + *
+ */ + CheckedFuture exists(YangInstanceIdentifier path); } diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java index 2a98406343..44ee61c116 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java @@ -7,19 +7,19 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl; -import static com.google.common.base.Preconditions.checkNotNull; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.Futures; +import static com.google.common.base.Preconditions.checkNotNull; /** * @@ -63,4 +63,16 @@ final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e)); } } -} \ No newline at end of file + + @Override public CheckedFuture exists(YangInstanceIdentifier path) { + LOG.debug("Tx: {} Exists: {}", getIdentifier(), path); + checkNotNull(path, "Path must not be null."); + + try { + return Futures.immediateCheckedFuture( + read(path).checkedGet().isPresent()); + } catch (ReadFailedException e) { + return Futures.immediateFailedCheckedFuture(e); + } + } +} diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java index 5c5e9c6b6d..ce7043fd47 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java @@ -61,4 +61,14 @@ class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e)); } } -} \ No newline at end of file + + @Override public CheckedFuture exists( + YangInstanceIdentifier path) { + try { + return Futures.immediateCheckedFuture( + read(path).checkedGet().isPresent()); + } catch (ReadFailedException e) { + return Futures.immediateFailedCheckedFuture(e); + } + } +} diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java index 4d38858667..c609e13e79 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java @@ -7,13 +7,10 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.concurrent.ExecutionException; - +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -35,9 +32,12 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import com.google.common.base.Optional; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; public class InMemoryDataStoreTest { @@ -185,6 +185,74 @@ public class InMemoryDataStoreTest { assertEquals( "After commit read: data", containerNode, afterCommitRead.get() ); } + + @Test + public void testExistsForExistingData() throws Exception { + + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + assertNotNull( writeTx ); + + ContainerNode containerNode = ImmutableContainerNodeBuilder.create() + .withNodeIdentifier( new NodeIdentifier( TestModel.TEST_QNAME ) ) + .addChild( ImmutableNodes.mapNodeBuilder( TestModel.OUTER_LIST_QNAME ) + .addChild( ImmutableNodes.mapEntry( TestModel.OUTER_LIST_QNAME, + TestModel.ID_QNAME, 1 ) ).build() ).build(); + + writeTx.merge( TestModel.TEST_PATH, containerNode ); + + CheckedFuture exists = + writeTx.exists(TestModel.TEST_PATH); + + assertEquals(true, exists.checkedGet()); + + DOMStoreThreePhaseCommitCohort ready = writeTx.ready(); + + ready.preCommit().get(); + + ready.commit().get(); + + DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction(); + assertNotNull( readTx ); + + exists = + readTx.exists(TestModel.TEST_PATH); + + assertEquals(true, exists.checkedGet()); + } + + @Test + public void testExistsForNonExistingData() throws Exception { + + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + assertNotNull( writeTx ); + + CheckedFuture exists = + writeTx.exists(TestModel.TEST_PATH); + + assertEquals(false, exists.checkedGet()); + + DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction(); + assertNotNull( readTx ); + + exists = + readTx.exists(TestModel.TEST_PATH); + + assertEquals(false, exists.checkedGet()); + } + + @Test(expected=ReadFailedException.class) + public void testExistsThrowsReadFailedException() throws Exception { + + DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction(); + assertNotNull( readTx ); + + readTx.close(); + + readTx.exists(TestModel.TEST_PATH).checkedGet(); + } + + + @Test(expected=ReadFailedException.class) public void testReadWithReadOnlyTransactionClosed() throws Throwable { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java index 04a99511a1..70d4f43365 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java @@ -7,12 +7,6 @@ */ package org.opendaylight.controller.sal.connect.netconf.sal.tx; -import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.CONFIG_SOURCE_RUNNING; -import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME; -import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME; -import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME; -import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure; - import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; @@ -35,6 +29,14 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.ExecutionException; + +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.CONFIG_SOURCE_RUNNING; +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME; +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME; +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME; +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure; + public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction { @@ -136,6 +138,19 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction throw new IllegalArgumentException(String.format("%s, Cannot read data %s for %s datastore, unknown datastore type", id, path, store)); } + @Override public CheckedFuture exists( + LogicalDatastoreType store, + YangInstanceIdentifier path) { + CheckedFuture>, ReadFailedException> + data = read(store, path); + + try { + return Futures.immediateCheckedFuture(data.get().isPresent()); + } catch (InterruptedException | ExecutionException e) { + return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e)); + } + } + static YangInstanceIdentifier toLegacyPath(final DataNormalizer normalizer, final YangInstanceIdentifier path, final RemoteDeviceId id) { try { return normalizer.toLegacy(path); diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadWriteTx.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadWriteTx.java index 3d2c3b9d44..11362a2f9b 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadWriteTx.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadWriteTx.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.connect.netconf.sal.tx; import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; @@ -23,6 +24,8 @@ import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import java.util.concurrent.ExecutionException; + public class NetconfDeviceReadWriteTx implements DOMDataReadWriteTransaction { private final DOMDataReadTransaction delegateReadTx; @@ -69,6 +72,19 @@ public class NetconfDeviceReadWriteTx implements DOMDataReadWriteTransaction { return delegateReadTx.read(store, path); } + @Override public CheckedFuture exists( + LogicalDatastoreType store, + YangInstanceIdentifier path) { + CheckedFuture>, ReadFailedException> + data = read(store, path); + + try { + return Futures.immediateCheckedFuture(data.get().isPresent()); + } catch (InterruptedException | ExecutionException e) { + return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e)); + } + } + @Override public Object getIdentifier() { return this; diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java index e8701f37e5..8dbc5b50ee 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java @@ -7,20 +7,12 @@ */ package org.opendaylight.controller.sal.restconf.impl; -import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION; -import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL; - import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.ListenableFuture; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import javax.ws.rs.core.Response.Status; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation; @@ -45,6 +37,16 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.ws.rs.core.Response.Status; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION; +import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL; + public class BrokerFacade { private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class); @@ -255,15 +257,20 @@ public class BrokerFacade { currentArguments.add(currentArg); YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments); - final Optional> datastoreData; + final Boolean exists; + try { - datastoreData = rwTx.read(store, currentPath).get(); - } catch (InterruptedException | ExecutionException e) { + + CheckedFuture future = + rwTx.exists(store, currentPath); + exists = future.checkedGet(); + } catch (ReadFailedException e) { LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e); throw new IllegalStateException("Failed to read pre-existing data", e); } - if (!datastoreData.isPresent() && iterator.hasNext()) { + + if (!exists && iterator.hasNext()) { rwTx.merge(store, currentPath, currentOp.createDefault(currentArg)); } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java index 146e88299a..6b25830240 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java @@ -8,21 +8,9 @@ package org.opendaylight.controller.sal.restconf.impl.test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; -import java.util.concurrent.Future; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -55,6 +43,19 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import java.util.concurrent.Future; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + /** * Unit tests for BrokerFacade. * @@ -111,6 +112,11 @@ public class BrokerFacadeTest { return Futures.immediateCheckedFuture(Optional.> of(dummyNode)); } + private CheckedFuture wrapExistence(Boolean exists) { + return Futures.immediateCheckedFuture(exists); + } + + /** * Value of this node shouldn't be important for testing purposes */ @@ -189,8 +195,14 @@ public class BrokerFacadeTest { CheckedFuture expFuture = mock(CheckedFuture.class); NormalizedNode dummyNode2 = createDummyNode("dummy:namespace2", "2014-07-01", "dummy local name2"); + when(rwTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn( wrapDummyNode(dummyNode2)); + + when(rwTransaction.exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn( + wrapExistence(true)); + + when(rwTransaction.submit()).thenReturn(expFuture); CheckedFuture actualFuture = brokerFacade.commitConfigurationDataPost(