/*
 * Copyright (c) 2014 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,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.controller.cluster.datastore;

import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.osgi.BundleDelegatingClassLoader;
import com.typesafe.config.ConfigFactory;
import org.opendaylight.controller.cluster.datastore.config.ConfigurationReader;
import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.osgi.framework.BundleContext;

import java.util.concurrent.atomic.AtomicReference;

public class DistributedDataStoreFactory {

    public static final String ACTOR_SYSTEM_NAME = "opendaylight-cluster-data";

    public static final String CONFIGURATION_NAME = "odl-cluster-data";

    private static AtomicReference<ActorSystem> persistentActorSystem = new AtomicReference<>();

    public static DistributedDataStore createInstance(String name, SchemaService schemaService,
                                                      DatastoreContext datastoreContext, BundleContext bundleContext) {

        ActorSystem actorSystem = getOrCreateInstance(bundleContext, datastoreContext.getConfigurationReader());
        Configuration config = new ConfigurationImpl("module-shards.conf", "modules.conf");
        final DistributedDataStore dataStore =
                new DistributedDataStore(actorSystem, name, new ClusterWrapperImpl(actorSystem),
                        config, datastoreContext);

        ShardStrategyFactory.setConfiguration(config);
        schemaService.registerSchemaContextListener(dataStore);
        return dataStore;
    }

    synchronized private static final ActorSystem getOrCreateInstance(final BundleContext bundleContext, ConfigurationReader configurationReader) {

        AtomicReference<ActorSystem> actorSystemReference = persistentActorSystem;
        String configurationName = CONFIGURATION_NAME;
        String actorSystemName = ACTOR_SYSTEM_NAME;

        if (actorSystemReference.get() != null){
            return actorSystemReference.get();
        }

        // Create an OSGi bundle classloader for actor system
        BundleDelegatingClassLoader classLoader = new BundleDelegatingClassLoader(bundleContext.getBundle(),
                Thread.currentThread().getContextClassLoader());

        ActorSystem system = ActorSystem.create(actorSystemName,
                ConfigFactory.load(configurationReader.read()).getConfig(configurationName), classLoader);
        system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");

        actorSystemReference.set(system);
        return system;
    }

}

@@ -301,17 +301,16 @@
 tml%0A */%0A
-%0A
 package 
@@ -786,61 +786,8 @@
 t;%0A%0A
-import java.util.concurrent.atomic.AtomicReference;%0A%0A
 publ
@@ -825,27 +825,27 @@
 ctory %7B%0A
-%0A
     p
-ublic
+rivate
  static 
@@ -906,27 +906,27 @@
 -data%22;%0A
-%0A
     p
-ublic
+rivate
  static 
@@ -999,32 +999,25 @@
  static 
-AtomicReference%3C
+volatile 
 ActorSys
@@ -1019,17 +1019,16 @@
 orSystem
-%3E
  persist
@@ -1049,30 +1049,11 @@
  = n
-ew AtomicReference%3C%3E()
+ull
 ;%0A%0A 
@@ -1829,21 +1829,8 @@
     
-synchronized 
 priv
@@ -1952,25 +1952,24 @@
 onReader) %7B%0A
-%0A
         Atom
@@ -1969,285 +1969,217 @@
    A
-tomicReference%3CActorSystem%3E actorSystemReference = persistentActorSystem;%0A        String configurationName = CONFIGURATION_NAME;%0A        String actorSystemName = ACTOR_SYSTEM_NAME;%0A%0A        if (actorSystemReference.get() != null)%7B%0A            return actorSystemReference.get();
+ctorSystem ret = persistentActorSystem;%0A        if (ret == null) %7B%0A            synchronized (DistributedDataStoreFactory.class) %7B%0A                ret = persistentActorSystem;%0A                if (ret == null) %7B
 %0A   
@@ -2179,27 +2179,28 @@
 ) %7B%0A        
-%7D%0A%0A
+    
         // C
@@ -2249,16 +2249,28 @@
  system%0A
+            
         
@@ -2386,16 +2386,24 @@
         
+        
 Thread.c
@@ -2456,26 +2456,23 @@
     
-ActorSystem system
+            ret
  = A
@@ -2493,25 +2493,35 @@
 ate(
-actorSystemName,%0A
+ACTOR_SYSTEM_NAME,%0A        
     
@@ -2593,25 +2593,26 @@
 fig(
-configurationName
+CONFIGURATION_NAME
 ), c
@@ -2632,22 +2632,31 @@
         
+    
-system
+        ret
 .actorOf
@@ -2733,41 +2733,91 @@
     
-actorSystemReference.set(system);
+            persistentActorSystem = ret;%0A                %7D%0A            %7D%0A        %7D%0A
 %0A   
@@ -2832,21 +2832,18 @@
 urn 
-system
+ret
 ;%0A    %7D%0A
 %0A%7D%0A
@@ -2839,11 +2839,10 @@
 ;%0A    %7D%0A
-%0A
 %7D%0A

Clarify DistributedDataStoreFactory