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%2Fdatastore%2Futils%2FActorContext.java;h=ad05a1ca71001285a8aed1f5afe16b1f511f3e96;hb=2f7c93174d7834a4c4aedacc9b88aa53a5a0422c;hp=afa773b4615e8905fffea10d42dbabd1cb046b0e;hpb=9a6190b662c5f8de44df872b0ba7e8dd17f8da13;p=controller.git diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java index afa773b461..ad05a1ca71 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java @@ -28,8 +28,13 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.RemovalNotification; import com.google.common.util.concurrent.RateLimiter; +import java.util.ArrayList; +import java.util.Collection; import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.GuardedBy; import org.opendaylight.controller.cluster.common.actor.CommonConfig; import org.opendaylight.controller.cluster.datastore.ClusterWrapper; import org.opendaylight.controller.cluster.datastore.Configuration; @@ -42,10 +47,11 @@ import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageException; import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard; import org.opendaylight.controller.cluster.datastore.messages.FindPrimary; +import org.opendaylight.controller.cluster.datastore.messages.LocalPrimaryShardFound; import org.opendaylight.controller.cluster.datastore.messages.LocalShardFound; import org.opendaylight.controller.cluster.datastore.messages.LocalShardNotFound; -import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound; import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo; +import org.opendaylight.controller.cluster.datastore.messages.RemotePrimaryShardFound; import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext; import org.opendaylight.controller.cluster.reporting.MetricsReporter; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree; @@ -64,7 +70,7 @@ import scala.concurrent.duration.FiniteDuration; * easily. An ActorContext can be freely passed around to local object instances * but should not be passed to actors especially remote actors */ -public class ActorContext { +public class ActorContext implements RemovalListener> { private static final Logger LOG = LoggerFactory.getLogger(ActorContext.class); private static final String DISTRIBUTED_DATA_STORE_METRIC_REGISTRY = "distributed-data-store"; private static final String METRIC_RATE = "rate"; @@ -103,6 +109,8 @@ public class ActorContext { private volatile SchemaContext schemaContext; private volatile boolean updated; private final MetricRegistry metricRegistry = MetricsReporter.getInstance(DatastoreContext.METRICS_DOMAIN).getMetricsRegistry(); + @GuardedBy("shardInfoListeners") + private final Collection> shardInfoListeners = new ArrayList<>(); public ActorContext(ActorSystem actorSystem, ActorRef shardManager, ClusterWrapper clusterWrapper, Configuration configuration) { @@ -145,6 +153,7 @@ public class ActorContext { primaryShardInfoCache = CacheBuilder.newBuilder() .expireAfterWrite(datastoreContext.getShardLeaderElectionTimeout().duration().toMillis(), TimeUnit.MILLISECONDS) + .removalListener(this) .build(); } @@ -209,14 +218,13 @@ public class ActorContext { return future.transform(new Mapper() { @Override public PrimaryShardInfo checkedApply(Object response) throws Exception { - if(response instanceof PrimaryFound) { - PrimaryFound found = (PrimaryFound)response; - - LOG.debug("Primary found {}", found.getPrimaryPath()); - ActorSelection actorSelection = actorSystem.actorSelection(found.getPrimaryPath()); - PrimaryShardInfo info = new PrimaryShardInfo(actorSelection, Optional.absent()); - primaryShardInfoCache.put(shardName, Futures.successful(info)); - return info; + if(response instanceof RemotePrimaryShardFound) { + LOG.debug("findPrimaryShardAsync received: {}", response); + return onPrimaryShardFound(shardName, ((RemotePrimaryShardFound)response).getPrimaryPath(), null); + } else if(response instanceof LocalPrimaryShardFound) { + LOG.debug("findPrimaryShardAsync received: {}", response); + LocalPrimaryShardFound found = (LocalPrimaryShardFound)response; + return onPrimaryShardFound(shardName, found.getPrimaryPath(), found.getLocalShardDataTree()); } else if(response instanceof NotInitializedException) { throw (NotInitializedException)response; } else if(response instanceof PrimaryNotFoundException) { @@ -231,6 +239,20 @@ public class ActorContext { }, FIND_PRIMARY_FAILURE_TRANSFORMER, getClientDispatcher()); } + private PrimaryShardInfo onPrimaryShardFound(String shardName, String primaryActorPath, + DataTree localShardDataTree) { + ActorSelection actorSelection = actorSystem.actorSelection(primaryActorPath); + PrimaryShardInfo info = new PrimaryShardInfo(actorSelection, Optional.fromNullable(localShardDataTree)); + primaryShardInfoCache.put(shardName, Futures.successful(info)); + + synchronized (shardInfoListeners) { + for (ShardInfoListenerRegistration reg : shardInfoListeners) { + reg.getInstance().onShardInfoUpdated(shardName, info); + } + } + return info; + } + /** * Finds a local shard given its shard name and return it's ActorRef * @@ -370,8 +392,7 @@ public class ActorContext { } public void shutdown() { - shardManager.tell(PoisonPill.getInstance(), null); - actorSystem.shutdown(); + shardManager.tell(PoisonPill.getInstance(), ActorRef.noSender()); } public ClusterWrapper getClusterWrapper() { @@ -559,4 +580,28 @@ public class ActorContext { Cache> getPrimaryShardInfoCache() { return primaryShardInfoCache; } + + public ShardInfoListenerRegistration registerShardInfoListener(final T listener) { + final ShardInfoListenerRegistration reg = new ShardInfoListenerRegistration(listener, this); + + synchronized (shardInfoListeners) { + shardInfoListeners.add(reg); + } + return reg; + } + + protected void removeShardInfoListener(final ShardInfoListenerRegistration registration) { + synchronized (shardInfoListeners) { + shardInfoListeners.remove(registration); + } + } + + @Override + public void onRemoval(final RemovalNotification> notification) { + synchronized (shardInfoListeners) { + for (ShardInfoListenerRegistration reg : shardInfoListeners) { + reg.getInstance().onShardInfoUpdated(notification.getKey(), null); + } + } + } }