CDS: Implement front-end support for local transactions
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / DistributedDataStore.java
index 69c127f2897017f218222b2a95b270b1bcc9f0de..18266658d3de421f592a5892b06b7a8baeec07f5 100644 (file)
@@ -8,9 +8,11 @@
 
 package org.opendaylight.controller.cluster.datastore;
 
+import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Uninterruptibles;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardManagerIdentifier;
@@ -61,6 +63,8 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener,
 
     private final String type;
 
+    private final TransactionContextFactory txContextFactory;
+
     public DistributedDataStore(ActorSystem actorSystem, ClusterWrapper cluster,
             Configuration configuration, DatastoreContext datastoreContext) {
         Preconditions.checkNotNull(actorSystem, "actorSystem should not be null");
@@ -77,14 +81,13 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener,
         String shardDispatcher =
                 new Dispatchers(actorSystem.dispatchers()).getDispatcherPath(Dispatchers.DispatcherType.Shard);
 
-        actorContext = new ActorContext(actorSystem, actorSystem.actorOf(
-                ShardManager.props(cluster, configuration, datastoreContext, waitTillReadyCountDownLatch)
-                        .withDispatcher(shardDispatcher).withMailbox(ActorContext.MAILBOX), shardManagerId ),
-                cluster, configuration, datastoreContext);
+        actorContext = new ActorContext(actorSystem, createShardManager(actorSystem, cluster, configuration,
+                datastoreContext, shardDispatcher, shardManagerId ), cluster, configuration, datastoreContext);
 
         this.waitTillReadyTimeInMillis =
                 actorContext.getDatastoreContext().getShardLeaderElectionTimeout().duration().toMillis() * READY_WAIT_FACTOR;
 
+        this.txContextFactory = TransactionContextFactory.create(actorContext);
 
         datastoreConfigMXBean = new DatastoreConfigurationMXBeanImpl(datastoreContext.getDataStoreMXBeanType());
         datastoreConfigMXBean.setContext(datastoreContext);
@@ -96,10 +99,10 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener,
 
     public DistributedDataStore(ActorContext actorContext) {
         this.actorContext = Preconditions.checkNotNull(actorContext, "actorContext should not be null");
+        this.txContextFactory = TransactionContextFactory.create(actorContext);
         this.type = UNKNOWN_TYPE;
         this.waitTillReadyTimeInMillis =
                 actorContext.getDatastoreContext().getShardLeaderElectionTimeout().duration().toMillis() * READY_WAIT_FACTOR;
-
     }
 
     public void setCloseable(AutoCloseable closeable) {
@@ -144,24 +147,24 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener,
 
     @Override
     public DOMStoreTransactionChain createTransactionChain() {
-        return new TransactionChainProxy(actorContext);
+        return txContextFactory.createTransactionChain();
     }
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_ONLY);
+       return new TransactionProxy(txContextFactory, TransactionType.READ_ONLY);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
         actorContext.acquireTxCreationPermit();
-        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.WRITE_ONLY);
+        return new TransactionProxy(txContextFactory, TransactionType.WRITE_ONLY);
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
         actorContext.acquireTxCreationPermit();
-        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_WRITE);
+        return new TransactionProxy(txContextFactory, TransactionType.READ_WRITE);
     }
 
     @Override
@@ -182,15 +185,17 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener,
         datastoreConfigMXBean.unregisterMBean();
         datastoreInfoMXBean.unregisterMBean();
 
-        if(closeable != null) {
+        if (closeable != null) {
             try {
                 closeable.close();
             } catch (Exception e) {
-                LOG.debug("Error closing insance", e);
+                LOG.debug("Error closing instance", e);
             }
         }
 
+        txContextFactory.close();
         actorContext.shutdown();
+        DistributedDataStoreFactory.destroyInstance(this);
     }
 
     @VisibleForTesting
@@ -212,6 +217,25 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener,
         }
     }
 
+    private ActorRef createShardManager(ActorSystem actorSystem, ClusterWrapper cluster, Configuration configuration,
+                                        DatastoreContext datastoreContext, String shardDispatcher, String shardManagerId){
+        Exception lastException = null;
+
+        for(int i=0;i<100;i++) {
+            try {
+                return actorSystem.actorOf(
+                        ShardManager.props(cluster, configuration, datastoreContext, waitTillReadyCountDownLatch)
+                                .withDispatcher(shardDispatcher).withMailbox(ActorContext.MAILBOX), shardManagerId);
+            } catch (Exception e){
+                lastException = e;
+                Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
+                LOG.debug(String.format("Could not create actor %s because of %s - waiting for sometime before retrying (retry count = %d)", shardManagerId, e.getMessage(), i));
+            }
+        }
+
+        throw new IllegalStateException("Failed to create Shard Manager", lastException);
+    }
+
     @VisibleForTesting
     public CountDownLatch getWaitTillReadyCountDownLatch() {
         return waitTillReadyCountDownLatch;