From a1ea6554ff025f333b171637b37a9ad87c7846ea Mon Sep 17 00:00:00 2001 From: Moiz Raja Date: Sun, 10 Aug 2014 16:18:33 -0700 Subject: [PATCH] Add exists method on DOMStoreReadTransaction and DOMDataReadTransaction Introducing this API does not impact clients as it is mostly internal. One reason for adding this API is because of ensureParentsByMerge used in a couple of places which keeps checking if a parent node exists by reading a node to figure out if it exists. This is fine for the InMemoryDataStore but it can be terrible in a distributed data store where the shard which contains the data is remote. All sorts of overhead is associated with a remote read including serialization which can actually be pretty expensive. Change-Id: Ib5be5f6dc60be683d7a04c81dad08c56cd5681f4 Signed-off-by: Moiz Raja --- .../impl/AbstractReadWriteTransaction.java | 19 +- ...rdedBackwardsCompatibleDataBrokerTest.java | 72 ++ .../test/DataBrokerTestCustomizer.java | 6 + .../transaction/ShardTransactionMessages.java | 960 +++++++++++++++++- .../src/main/resources/ShardTransaction.proto | 8 + .../datastore/ShardReadTransaction.java | 5 +- .../datastore/ShardReadWriteTransaction.java | 3 + .../cluster/datastore/ShardTransaction.java | 26 +- .../cluster/datastore/TransactionProxy.java | 110 +- .../datastore/messages/DataExists.java | 40 + .../datastore/messages/DataExistsReply.java | 38 + .../ShardTransactionFailureTest.java | 35 + .../datastore/ShardTransactionTest.java | 86 ++ .../datastore/TransactionProxyTest.java | 61 +- .../sal/dom/api/DOMDataReadTransaction.java | 18 + .../impl/DOMForwardedReadOnlyTransaction.java | 6 + .../DOMForwardedReadWriteTransaction.java | 8 +- .../broker/BackwardsCompatibleMountPoint.java | 33 +- .../spi/data/DOMStoreReadTransaction.java | 16 + .../impl/SnapshotBackedReadTransaction.java | 26 +- .../SnapshotBackedReadWriteTransaction.java | 12 +- .../dom/store/impl/InMemoryDataStoreTest.java | 88 +- .../sal/tx/NetconfDeviceReadOnlyTx.java | 27 +- .../sal/tx/NetconfDeviceReadWriteTx.java | 16 + .../sal/restconf/impl/BrokerFacade.java | 33 +- .../restconf/impl/test/BrokerFacadeTest.java | 36 +- 26 files changed, 1670 insertions(+), 118 deletions(-) create mode 100644 opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExists.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExistsReply.java 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( -- 2.36.6