Bug 4957 RoleContext updated with initialization
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / role / RoleContextImpl.java
index 06305e1879d4957150b7a19338897e2522f0a5b0..1cfb39bc8eb98661f87e92c5f2bb1443692e562a 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.SettableFuture;
 import java.util.concurrent.Future;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
@@ -41,18 +42,19 @@ import org.slf4j.LoggerFactory;
 public class RoleContextImpl implements RoleContext {
     private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
 
-    private EntityOwnershipService entityOwnershipService;
+    private final EntityOwnershipService entityOwnershipService;
     private EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
     private final RpcProviderRegistry rpcProviderRegistry;
-    private DeviceContext deviceContext;
-    private Entity entity;
-    private OpenflowOwnershipListener openflowOwnershipListener;
+    private final DeviceContext deviceContext;
+    private final Entity entity;
+    private final OpenflowOwnershipListener openflowOwnershipListener;
     private SalRoleService salRoleService;
     private FutureCallback<Boolean> roleChangeCallback;
 
+    private final SettableFuture<OfpRole> initRoleChangeFuture;
 
-    public RoleContextImpl(DeviceContext deviceContext, RpcProviderRegistry rpcProviderRegistry,
-                           EntityOwnershipService entityOwnershipService, OpenflowOwnershipListener openflowOwnershipListener) {
+    public RoleContextImpl(final DeviceContext deviceContext, final RpcProviderRegistry rpcProviderRegistry,
+                           final EntityOwnershipService entityOwnershipService, final OpenflowOwnershipListener openflowOwnershipListener) {
         this.entityOwnershipService = entityOwnershipService;
         this.rpcProviderRegistry = rpcProviderRegistry;
         this.deviceContext = deviceContext;
@@ -61,12 +63,21 @@ public class RoleContextImpl implements RoleContext {
         this.openflowOwnershipListener =  openflowOwnershipListener;
         salRoleService = new SalRoleServiceImpl(this, deviceContext);
 
-        //make a call to entity ownership service and listen for notifications from the service
-        requestOpenflowEntityOwnership();
+        initRoleChangeFuture = SettableFuture.create();
     }
 
     @Override
-    public void facilitateRoleChange(FutureCallback<Boolean> roleChangeCallback) {
+    public Future<OfpRole> initialization() throws CandidateAlreadyRegisteredException {
+        LOG.debug("Initialization requestOpenflowEntityOwnership for entity {}", entity);
+        openflowOwnershipListener.registerRoleChangeListener(this);
+        entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity);
+        LOG.info("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext
+                .getPrimaryConnectionContext().getNodeId().getValue());
+        return initRoleChangeFuture;
+    }
+
+    @Override
+    public void facilitateRoleChange(final FutureCallback<Boolean> roleChangeCallback) {
         this.roleChangeCallback = roleChangeCallback;
         if (!isDeviceConnected()) {
             throw new IllegalStateException(
@@ -83,7 +94,7 @@ public class RoleContextImpl implements RoleContext {
             // The role change listener must be registered after registering a candidate
             openflowOwnershipListener.registerRoleChangeListener(this);
             LOG.info("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext.getPrimaryConnectionContext().getNodeId().getValue());
-        } catch (CandidateAlreadyRegisteredException e) {
+        } catch (final CandidateAlreadyRegisteredException e) {
             // we can log and move for this error, as listener is present and role changes will be served.
             LOG.error("Candidate - Entity already registered with Openflow candidate ", entity, e );
         }
@@ -91,14 +102,24 @@ public class RoleContextImpl implements RoleContext {
 
     @Override
     public void onRoleChanged(final OfpRole oldRole, final OfpRole newRole) {
+        LOG.trace("onRoleChanged method call for Entity {}", entity);
 
         if (!isDeviceConnected()) {
             // this can happen as after the disconnect, we still get a last messsage from EntityOwnershipService.
             LOG.info("Device {} is disconnected from this node. Hence not attempting a role change.",
                     deviceContext.getPrimaryConnectionContext().getNodeId());
+            if (!initRoleChangeFuture.isDone()) {
+                LOG.debug("RoleChange is not valid for initialization Entity {} anymore - Device is disconnected", entity);
+                initRoleChangeFuture.cancel(true);
+            }
             return;
         }
 
+        if (!initRoleChangeFuture.isDone()) {
+            LOG.debug("Initialization Role for entity {} is chosed {}", entity, newRole);
+            initRoleChangeFuture.set(newRole);
+        }
+
         LOG.debug("Role change received from ownership listener from {} to {} for device:{}", oldRole, newRole,
                 deviceContext.getPrimaryConnectionContext().getNodeId());
 
@@ -107,11 +128,11 @@ public class RoleContextImpl implements RoleContext {
                 .setNode(new NodeRef(deviceContext.getDeviceState().getNodeInstanceIdentifier()))
                 .build();
 
-        Future<RpcResult<SetRoleOutput>> setRoleOutputFuture = salRoleService.setRole(setRoleInput);
+        final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture = salRoleService.setRole(setRoleInput);
 
         Futures.addCallback(JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture), new FutureCallback<RpcResult<SetRoleOutput>>() {
             @Override
-            public void onSuccess(RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
+            public void onSuccess(final RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
                 LOG.debug("Rolechange {} successful made on switch :{}", newRole,
                         deviceContext.getPrimaryConnectionContext().getNodeId());
                 deviceContext.getDeviceState().setRole(newRole);
@@ -121,7 +142,7 @@ public class RoleContextImpl implements RoleContext {
             }
 
             @Override
-            public void onFailure(Throwable throwable) {
+            public void onFailure(final Throwable throwable) {
                 LOG.error("Error in setRole {} for device {} ", newRole,
                         deviceContext.getPrimaryConnectionContext().getNodeId(), throwable);
                 if (roleChangeCallback != null) {
@@ -140,11 +161,11 @@ public class RoleContextImpl implements RoleContext {
     }
 
     @Override
-    public void onDeviceContextClosed(DeviceContext deviceContext) {
+    public void onDeviceContextClosed(final DeviceContext deviceContext) {
         try {
             LOG.debug("onDeviceContextClosed called");
             this.close();
-        } catch (Exception e) {
+        } catch (final Exception e) {
             LOG.error("Exception in onDeviceContextClosed of RoleContext", e);
         }
     }
@@ -177,7 +198,7 @@ public class RoleContextImpl implements RoleContext {
     }
 
     @VisibleForTesting
-    public void setSalRoleService(SalRoleService salRoleService) {
+    public void setSalRoleService(final SalRoleService salRoleService) {
         this.salRoleService = salRoleService;
     }
 }