X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fsharding%2FDistributedShardedDOMDataTree.java;h=4ffc575c1afcf08ec4d5c35101999b90c61af502;hb=refs%2Fchanges%2F99%2F56399%2F5;hp=506498ce9a77fecbf9d7911296aafb49c1160f11;hpb=be3bc49185f935ad2672b08e031f602eca594d1e;p=controller.git diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTree.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTree.java index 506498ce9a..4ffc575c1a 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTree.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2016, 2017 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, @@ -307,7 +307,7 @@ public class DistributedShardedDOMDataTree implements DOMDataTreeService, DOMDat LOG.debug("{} - Received success from remote nodes, creating producer:{}", distributedConfigDatastore.getActorContext().getClusterWrapper().getCurrentMemberName(), subtrees); return new ProxyProducer(producer, subtrees, shardedDataTreeActor, - distributedConfigDatastore.getActorContext()); + distributedConfigDatastore.getActorContext(), shards); } else if (response instanceof Exception) { closeProducer(producer); throw Throwables.propagate((Exception) response); @@ -402,7 +402,7 @@ public class DistributedShardedDOMDataTree implements DOMDataTreeService, DOMDat prefix.getDatastoreType().equals(org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION) ? distributedConfigDatastore : distributedOperDatastore; - try (final DOMDataTreeProducer producer = localCreateProducer(Collections.singletonList(prefix))) { + try (DOMDataTreeProducer producer = localCreateProducer(Collections.singletonList(prefix))) { final Entry entry = createDatastoreClient(shardName, distributedDataStore.getActorContext()); @@ -464,8 +464,9 @@ public class DistributedShardedDOMDataTree implements DOMDataTreeService, DOMDat DOMDataTreePrefixTableEntry> lookupShardFrontend( final DOMDataTreeIdentifier prefix) { - return shards.lookup(prefix); - + synchronized (shards) { + return shards.lookup(prefix); + } } DOMDataTreeProducer localCreateProducer(final Collection prefix) { @@ -641,14 +642,21 @@ public class DistributedShardedDOMDataTree implements DOMDataTreeService, DOMDat @GuardedBy("shardAccessMap") private final Map shardAccessMap = new HashMap<>(); + // We don't have to guard access to shardTable in ProxyProducer. + // ShardTable's entries relevant to this ProxyProducer shouldn't + // change during producer's lifetime. + private final DOMDataTreePrefixTable> shardTable; + ProxyProducer(final DOMDataTreeProducer delegate, final Collection subtrees, final ActorRef shardDataTreeActor, - final ActorContext actorContext) { + final ActorContext actorContext, + final DOMDataTreePrefixTable> shardLayout) { this.delegate = Preconditions.checkNotNull(delegate); this.subtrees = Preconditions.checkNotNull(subtrees); this.shardDataTreeActor = Preconditions.checkNotNull(shardDataTreeActor); this.actorContext = Preconditions.checkNotNull(actorContext); + this.shardTable = Preconditions.checkNotNull(shardLayout); } @Nonnull @@ -669,13 +677,14 @@ public class DistributedShardedDOMDataTree implements DOMDataTreeService, DOMDat @SuppressWarnings("checkstyle:IllegalCatch") public void close() throws DOMDataTreeProducerException { delegate.close(); + synchronized (shardAccessMap) { shardAccessMap.values().forEach(CDSShardAccessImpl::close); } final Object o = actorContext.executeOperation(shardDataTreeActor, new ProducerRemoved(subtrees)); if (o instanceof DOMDataTreeProducerException) { - throw ((DOMDataTreeProducerException) o); + throw (DOMDataTreeProducerException) o; } else if (o instanceof Throwable) { throw new DOMDataTreeProducerException("Unable to close producer", (Throwable) o); } @@ -689,19 +698,28 @@ public class DistributedShardedDOMDataTree implements DOMDataTreeService, DOMDat @Nonnull @Override public CDSShardAccess getShardAccess(@Nonnull final DOMDataTreeIdentifier subtree) { + Preconditions.checkArgument( + subtrees.stream().anyMatch(dataTreeIdentifier -> dataTreeIdentifier.contains(subtree)), + "Subtree {} is not controlled by this producer {}", subtree, this); + + final DOMDataTreePrefixTableEntry> lookup = + shardTable.lookup(subtree); + Preconditions.checkState(lookup != null, "Subtree {} is not contained in any registered shard."); + + final DOMDataTreeIdentifier lookupId = lookup.getValue().getPrefix(); + synchronized (shardAccessMap) { - Preconditions.checkArgument(subtrees.contains(subtree), - "Subtree {} is not controlled by this producer {}", subtree, this); - if (shardAccessMap.get(subtree) != null) { - return shardAccessMap.get(subtree); + if (shardAccessMap.get(lookupId) != null) { + return shardAccessMap.get(lookupId); } // TODO Maybe we can have static factory method and return the same instance // for same subtrees. But maybe it is not needed since there can be only one // producer attached to some subtree at a time. And also how we can close ShardAccess // then - final CDSShardAccessImpl shardAccess = new CDSShardAccessImpl(subtree, actorContext); - return shardAccessMap.put(subtree, shardAccess); + final CDSShardAccessImpl shardAccess = new CDSShardAccessImpl(lookupId, actorContext); + shardAccessMap.put(lookupId, shardAccess); + return shardAccess; } } }