Convert sal-distributed-datastore to OSGi DS
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / AbstractDataStore.java
index bc4a8e739577d6264038594d67980673fc937fe2..d6958a70d72030ce20b01b8ba30e39149535ab06 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.cluster.datastore;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
 import akka.actor.ActorRef;
@@ -17,6 +18,7 @@ import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Throwables;
 import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -43,8 +45,8 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.dom.spi.store.DOMStoreTreeChangePublisher;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import scala.concurrent.duration.Duration;
@@ -52,7 +54,7 @@ import scala.concurrent.duration.Duration;
 /**
  * Base implementation of a distributed DOMStore.
  */
-public abstract class AbstractDataStore implements DistributedDataStoreInterface, SchemaContextListener,
+public abstract class AbstractDataStore implements DistributedDataStoreInterface, EffectiveModelContextListener,
         DatastoreContextPropertiesUpdater.Listener, DOMStoreTreeChangePublisher,
         DOMDataTreeCommitCohortRegistry, AutoCloseable {
 
@@ -159,6 +161,21 @@ public abstract class AbstractDataStore implements DistributedDataStoreInterface
         requireNonNull(treeId, "treeId should not be null");
         requireNonNull(listener, "listener should not be null");
 
+        /*
+         * We need to potentially deal with multi-shard composition for registration targeting the root of the data
+         * store. If that is the case, we delegate to a more complicated setup invol
+         */
+        if (treeId.isEmpty()) {
+            // User is targeting root of the datastore. If there is more than one shard, we have to register with them
+            // all and perform data composition.
+            final Set<String> shardNames = actorUtils.getConfiguration().getAllShardNames();
+            if (shardNames.size() > 1) {
+                checkArgument(listener instanceof ClusteredDOMDataTreeChangeListener,
+                    "Cannot listen on root without non-clustered listener %s", listener);
+                return new RootDataTreeChangeListenerProxy<>(actorUtils, listener, shardNames);
+            }
+        }
+
         final String shardName = actorUtils.getShardStrategyFactory().getStrategy(treeId).findShard(treeId);
         LOG.debug("Registering tree listener: {} for tree: {} shard: {}", listener, treeId, shardName);
 
@@ -169,7 +186,6 @@ public abstract class AbstractDataStore implements DistributedDataStoreInterface
         return listenerRegistrationProxy;
     }
 
-
     @Override
     public <C extends DOMDataTreeCommitCohort> DOMDataTreeCommitCohortRegistration<C> registerCommitCohort(
             final DOMDataTreeIdentifier subtree, final C cohort) {
@@ -187,8 +203,8 @@ public abstract class AbstractDataStore implements DistributedDataStoreInterface
     }
 
     @Override
-    public void onGlobalContextUpdated(final SchemaContext schemaContext) {
-        actorUtils.setSchemaContext(schemaContext);
+    public void onModelContextUpdated(final EffectiveModelContext newModelContext) {
+        actorUtils.setSchemaContext(newModelContext);
     }
 
     @Override
@@ -237,13 +253,9 @@ public abstract class AbstractDataStore implements DistributedDataStoreInterface
 
         final Duration toWait = initialSettleTime();
         try {
-            if (toWait.isFinite()) {
-                if (!waitTillReadyCountDownLatch.await(toWait.toNanos(), TimeUnit.NANOSECONDS)) {
-                    LOG.error("Shard leaders failed to settle in {}, giving up", toWait);
-                    return;
-                }
-            } else {
-                waitTillReadyCountDownLatch.await();
+            if (!awaitReadiness(toWait)) {
+                LOG.error("Shard leaders failed to settle in {}, giving up", toWait);
+                return;
             }
         } catch (InterruptedException e) {
             LOG.error("Interrupted while waiting for shards to settle", e);
@@ -253,6 +265,21 @@ public abstract class AbstractDataStore implements DistributedDataStoreInterface
         LOG.debug("Data store {} is now ready", identifier);
     }
 
+    @Beta
+    public boolean awaitReadiness() throws InterruptedException {
+        return awaitReadiness(initialSettleTime());
+    }
+
+    @Beta
+    public boolean awaitReadiness(final Duration toWait) throws InterruptedException {
+        if (toWait.isFinite()) {
+            return waitTillReadyCountDownLatch.await(toWait.toNanos(), TimeUnit.NANOSECONDS);
+        }
+
+        waitTillReadyCountDownLatch.await();
+        return true;
+    }
+
     @Beta
     public void awaitReadiness(final long timeout, final TimeUnit unit) throws InterruptedException, TimeoutException {
         if (!waitTillReadyCountDownLatch.await(timeout, unit)) {
@@ -285,11 +312,11 @@ public abstract class AbstractDataStore implements DistributedDataStoreInterface
         return waitTillReadyCountDownLatch;
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerProxyListener(
-            final YangInstanceIdentifier shardLookup,
-            final YangInstanceIdentifier insideShard,
-            final org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener delegate) {
+            final YangInstanceIdentifier shardLookup, final YangInstanceIdentifier insideShard,
+            final DOMDataTreeChangeListener delegate) {
 
         requireNonNull(shardLookup, "shardLookup should not be null");
         requireNonNull(insideShard, "insideShard should not be null");
@@ -309,10 +336,10 @@ public abstract class AbstractDataStore implements DistributedDataStoreInterface
         return (ListenerRegistration<L>) listenerRegistrationProxy;
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerShardConfigListener(
-            final YangInstanceIdentifier internalPath,
-            final DOMDataTreeChangeListener delegate) {
+            final YangInstanceIdentifier internalPath, final DOMDataTreeChangeListener delegate) {
         requireNonNull(delegate, "delegate should not be null");
 
         LOG.debug("Registering a listener for the configuration shard: {}", internalPath);