Centralize NetconfNode/InetSocketAddress conversion
[netconf.git] / netconf / netconf-topology-singleton / src / main / java / org / opendaylight / netconf / topology / singleton / impl / NetconfTopologyContext.java
index 0f8255cdaa3dc5140f38928877d228d0c4752e15..0cb78da8aa5d7c7f24875a3612aa866da0023960 100644 (file)
@@ -5,58 +5,67 @@
  * 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.netconf.topology.singleton.impl;
 
-import static org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
+import static java.util.Objects.requireNonNull;
 
 import akka.actor.ActorRef;
 import akka.cluster.Cluster;
 import akka.dispatch.OnComplete;
 import akka.pattern.Patterns;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.Futures;
+import akka.util.Timeout;
 import com.google.common.util.concurrent.ListenableFuture;
-import javax.annotation.Nonnull;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.topology.singleton.api.RemoteDeviceConnector;
 import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
 import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
+import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yangtools.util.concurrent.FluentFutures;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import scala.concurrent.Future;
 
-class NetconfTopologyContext implements ClusterSingletonService {
+class NetconfTopologyContext implements ClusterSingletonService, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyContext.class);
 
     private final ServiceGroupIdentifier serviceGroupIdent;
+    private final Timeout actorResponseWaitTime;
+    private final DOMMountPointService mountService;
+    private final DeviceActionFactory deviceActionFactory;
+
     private NetconfTopologySetup netconfTopologyDeviceSetup;
     private RemoteDeviceId remoteDeviceId;
     private RemoteDeviceConnector remoteDeviceConnector;
     private NetconfNodeManager netconfNodeManager;
-    private boolean finalClose = false;
-    private boolean isMaster;
-
     private ActorRef masterActorRef;
+    private final AtomicBoolean closed = new AtomicBoolean(false);
+    private final AtomicBoolean stopped = new AtomicBoolean(false);
+    private volatile boolean isMaster;
 
     NetconfTopologyContext(final NetconfTopologySetup netconfTopologyDeviceSetup,
-                           final ServiceGroupIdentifier serviceGroupIdent) {
-        this.netconfTopologyDeviceSetup = Preconditions.checkNotNull(netconfTopologyDeviceSetup);
+            final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
+            final DOMMountPointService mountService, final DeviceActionFactory deviceActionFactory) {
+        this.netconfTopologyDeviceSetup = requireNonNull(netconfTopologyDeviceSetup);
         this.serviceGroupIdent = serviceGroupIdent;
-
-        remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
-                netconfTopologyDeviceSetup.getNode().getAugmentation(NetconfNode.class));
-
-        remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
-
+        this.actorResponseWaitTime = actorResponseWaitTime;
+        this.mountService = mountService;
+        this.deviceActionFactory = deviceActionFactory;
+
+        final var node = netconfTopologyDeviceSetup.getNode();
+        remoteDeviceId = NetconfNodeUtils.toRemoteDeviceId(node.getNodeId(), node.augmentation(NetconfNode.class));
+        remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId,
+            deviceActionFactory);
         netconfNodeManager = createNodeDeviceManager();
-
     }
 
     @Override
@@ -71,34 +80,29 @@ class NetconfTopologyContext implements ClusterSingletonService {
             netconfNodeManager = null;
         }
 
-        if (!finalClose) {
-            final String masterAddress = Cluster.get(netconfTopologyDeviceSetup.getActorSystem()).selfAddress().toString();
+        if (!closed.get()) {
+            final String masterAddress =
+                    Cluster.get(netconfTopologyDeviceSetup.getActorSystem()).selfAddress().toString();
             masterActorRef = netconfTopologyDeviceSetup.getActorSystem().actorOf(NetconfNodeActor.props(
-                    netconfTopologyDeviceSetup, remoteDeviceId, DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY),
+                    netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService),
                     NetconfTopologyUtils.createMasterActorName(remoteDeviceId.getName(), masterAddress));
 
-            remoteDeviceConnector.startRemoteDeviceConnection(masterActorRef);
+            remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
         }
 
     }
 
     // called when master is down/changed to slave
     @Override
-    public ListenableFuture<Void> closeServiceInstance() {
+    public ListenableFuture<?> closeServiceInstance() {
 
-        if (!finalClose) {
+        if (!closed.get()) {
             // in case that master changes role to slave, new NodeDeviceManager must be created and listener registered
             netconfNodeManager = createNodeDeviceManager();
         }
-        if (masterActorRef != null) {
-            netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
-            masterActorRef = null;
-        }
-        if (remoteDeviceConnector != null) {
-            remoteDeviceConnector.stopRemoteDeviceConnection();
-        }
+        stopDeviceConnectorAndActor();
 
-        return Futures.immediateCheckedFuture(null);
+        return FluentFutures.immediateNullFluentFuture();
     }
 
     @Override
@@ -108,39 +112,34 @@ class NetconfTopologyContext implements ClusterSingletonService {
 
     private NetconfNodeManager createNodeDeviceManager() {
         final NetconfNodeManager ndm =
-                new NetconfNodeManager(netconfTopologyDeviceSetup, remoteDeviceId, DEFAULT_SCHEMA_REPOSITORY,
-                        DEFAULT_SCHEMA_REPOSITORY);
+                new NetconfNodeManager(netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService);
         ndm.registerDataTreeChangeListener(netconfTopologyDeviceSetup.getTopologyId(),
-                netconfTopologyDeviceSetup.getNode().getKey());
+                netconfTopologyDeviceSetup.getNode().key());
 
         return ndm;
     }
 
-    void closeFinal() throws Exception {
-        finalClose = true;
+    @Override
+    public void close() {
+        if (!closed.compareAndSet(false, true)) {
+            return;
+        }
 
         if (netconfNodeManager != null) {
             netconfNodeManager.close();
         }
+        stopDeviceConnectorAndActor();
 
-        if (remoteDeviceConnector != null) {
-            remoteDeviceConnector.stopRemoteDeviceConnection();
-        }
-
-        if (masterActorRef != null) {
-            netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
-            masterActorRef = null;
-        }
     }
 
     /**
-     * If configuration data was changed
+     * Refresh, if configuration data was changed.
      * @param setup new setup
      */
-    void refresh(@Nonnull final NetconfTopologySetup setup) {
-        netconfTopologyDeviceSetup = Preconditions.checkNotNull(setup);
-        remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
-                netconfTopologyDeviceSetup.getNode().getAugmentation(NetconfNode.class));
+    void refresh(final @NonNull NetconfTopologySetup setup) {
+        netconfTopologyDeviceSetup = requireNonNull(setup);
+        final var node = netconfTopologyDeviceSetup.getNode();
+        remoteDeviceId = NetconfNodeUtils.toRemoteDeviceId(node.getNodeId(), node.augmentation(NetconfNode.class));
 
         if (isMaster) {
             remoteDeviceConnector.stopRemoteDeviceConnection();
@@ -148,22 +147,41 @@ class NetconfTopologyContext implements ClusterSingletonService {
         if (!isMaster) {
             netconfNodeManager.refreshDevice(netconfTopologyDeviceSetup, remoteDeviceId);
         }
-        remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
+        remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId,
+            deviceActionFactory);
 
         if (isMaster) {
             final Future<Object> future = Patterns.ask(masterActorRef, new RefreshSetupMasterActorData(
-                    netconfTopologyDeviceSetup, remoteDeviceId), NetconfTopologyUtils.TIMEOUT);
-
+                netconfTopologyDeviceSetup, remoteDeviceId), actorResponseWaitTime);
             future.onComplete(new OnComplete<Object>() {
                 @Override
-                public void onComplete(final Throwable failure, final Object success) throws Throwable {
+                public void onComplete(final Throwable failure, final Object success) {
                     if (failure != null) {
-                        LOG.error("Failed to refresh master actor data: {}", failure);
+                        LOG.error("Failed to refresh master actor data", failure);
                         return;
                     }
-                    remoteDeviceConnector.startRemoteDeviceConnection(masterActorRef);
+                    remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
                 }
             }, netconfTopologyDeviceSetup.getActorSystem().dispatcher());
         }
     }
-}
+
+    private void stopDeviceConnectorAndActor() {
+        if (!stopped.compareAndSet(false, true)) {
+            return;
+        }
+        if (remoteDeviceConnector != null) {
+            remoteDeviceConnector.stopRemoteDeviceConnection();
+        }
+
+        if (masterActorRef != null) {
+            netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
+            masterActorRef = null;
+        }
+    }
+
+    protected MasterSalFacade newMasterSalFacade() {
+        return new MasterSalFacade(remoteDeviceId, netconfTopologyDeviceSetup.getActorSystem(), masterActorRef,
+                actorResponseWaitTime, mountService, netconfTopologyDeviceSetup.getDataBroker());
+    }
+}
\ No newline at end of file