BUG 1735 Registering a data change listener should be asynchronous
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / DistributedDataStore.java
index db01d515354a9d166e2b906d8cd7168e7c39deb0..bf541d95deadeb3e9ecce59c83cdb988934289a5 100644 (file)
@@ -10,9 +10,9 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
-
+import akka.dispatch.OnComplete;
+import akka.util.Timeout;
 import com.google.common.base.Preconditions;
-
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardManagerIdentifier;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
@@ -32,6 +32,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import scala.concurrent.Future;
 
 /**
  *
@@ -39,6 +40,7 @@ import org.slf4j.LoggerFactory;
 public class DistributedDataStore implements DOMStore, SchemaContextListener, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(DistributedDataStore.class);
+    public static final int REGISTER_DATA_CHANGE_LISTENER_TIMEOUT_FACTOR = 24; // 24 times the usual operation timeout
 
     private final ActorContext actorContext;
 
@@ -69,7 +71,7 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
     @Override
     public <L extends AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>>
                                               ListenerRegistration<L> registerChangeListener(
-        YangInstanceIdentifier path, L listener,
+        final YangInstanceIdentifier path, L listener,
         AsyncDataBroker.DataChangeScope scope) {
 
         Preconditions.checkNotNull(path, "path should not be null");
@@ -82,14 +84,29 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
 
         String shardName = ShardStrategyFactory.getStrategy(path).findShard(path);
 
-        Object result = actorContext.executeLocalShardOperation(shardName,
-            new RegisterChangeListener(path, dataChangeListenerActor.path(), scope));
-
-        if (result != null) {
-            RegisterChangeListenerReply reply = (RegisterChangeListenerReply) result;
-            return new DataChangeListenerRegistrationProxy(actorContext
-                .actorSelection(reply.getListenerRegistrationPath()), listener,
-                dataChangeListenerActor);
+        Future future = actorContext.executeLocalShardOperationAsync(shardName,
+            new RegisterChangeListener(path, dataChangeListenerActor.path(), scope),
+            new Timeout(actorContext.getOperationDuration().$times(
+                REGISTER_DATA_CHANGE_LISTENER_TIMEOUT_FACTOR)));
+
+        if (future != null) {
+            final DataChangeListenerRegistrationProxy listenerRegistrationProxy =
+                new DataChangeListenerRegistrationProxy(listener, dataChangeListenerActor);
+
+            future.onComplete(new OnComplete(){
+
+                @Override public void onComplete(Throwable failure, Object result)
+                    throws Throwable {
+                    if(failure != null){
+                        LOG.error("Failed to register listener at path " + path.toString(), failure);
+                        return;
+                    }
+                    RegisterChangeListenerReply reply = (RegisterChangeListenerReply) result;
+                    listenerRegistrationProxy.setListenerRegistrationActor(actorContext
+                        .actorSelection(reply.getListenerRegistrationPath()));
+                }
+            }, actorContext.getActorSystem().dispatcher());
+            return listenerRegistrationProxy;
         }
 
         LOG.debug(