*/
package org.opendaylight.openflowplugin.api.openflow.role;
+import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
-import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
* {@link org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService} returns
* {@link org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException}
* @return InitializationFuture for to know where first initial Election is done and we know role.
- * @throws CandidateAlreadyRegisteredException - we have registered Entity so drop actual connection
*/
- Future<OfpRole> initialization() throws CandidateAlreadyRegisteredException;
+ ListenableFuture<OfpRole> initialization();
@Override
void close();
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.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
}
@Override
- public Future<OfpRole> initialization() throws CandidateAlreadyRegisteredException {
+ public ListenableFuture<OfpRole> initialization() {
LOG.debug("Initialization requestOpenflowEntityOwnership for entity {}", entity);
- entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity);
- LOG.info("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext
- .getPrimaryConnectionContext().getNodeId().getValue());
+ try {
+ entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity);
+ LOG.debug("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext
+ .getPrimaryConnectionContext().getNodeId().getValue());
+ } catch (final CandidateAlreadyRegisteredException e) {
+ completeInitRoleChangeFuture(null, e);
+ }
return initRoleChangeFuture;
}
// 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);
- }
+ completeInitRoleChangeFuture(null, null);
return;
}
- if (!initRoleChangeFuture.isDone()) {
- LOG.debug("Initialization Role for entity {} is chosed {}", entity, newRole);
- // we don't want to wait for Device RoleChangeResponse in initial phase
- deviceContext.onClusterRoleChange(newRole);
- initRoleChangeFuture.set(newRole);
- }
-
LOG.debug("Role change received from ownership listener from {} to {} for device:{}", oldRole, newRole,
deviceContext.getPrimaryConnectionContext().getNodeId());
deviceContext.getPrimaryConnectionContext().getNodeId());
deviceContext.getDeviceState().setRole(newRole);
deviceContext.onClusterRoleChange(newRole);
+ completeInitRoleChangeFuture(newRole, null);
}
@Override
public void onFailure(final Throwable throwable) {
LOG.error("Error in setRole {} for device {} ", newRole,
deviceContext.getPrimaryConnectionContext().getNodeId(), throwable);
+ completeInitRoleChangeFuture(null, throwable);
}
});
}
+ void completeInitRoleChangeFuture(@Nullable final OfpRole role, @Nullable final Throwable throwable) {
+ if (initRoleChangeFuture.isDone()) {
+ return;
+ }
+ if (!isDeviceConnected()) {
+ LOG.debug("Device {} is disconnected from this node. Hence not attempting a role change.", deviceContext
+ .getPrimaryConnectionContext().getNodeId());
+ initRoleChangeFuture.cancel(true);
+ return;
+ }
+ if (throwable != null) {
+ LOG.warn("Connection Role change fail for entity {}", entity);
+ initRoleChangeFuture.setException(throwable);
+ } else if (role != null) {
+ LOG.debug("Initialization Role for entity {} is chosed {}", entity, role);
+ initRoleChangeFuture.set(role);
+ } else {
+ LOG.debug("Unexpected initialization Role Change close for entity {}", entity);
+ initRoleChangeFuture.cancel(true);
+ }
+ }
+
@Override
public void close() {
if (entityOwnershipCandidateRegistration != null) {
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
+import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
deviceContext.addDeviceContextClosedHandler(this);
Verify.verify(contexts.putIfAbsent(roleContext.getEntity(), roleContext) == null,
"RoleCtx for master Node {} is still not close.", deviceContext.getDeviceState().getNodeId());
- OfpRole role = null;
- try {
- role = roleContext.initialization().get(5, TimeUnit.SECONDS);
- } catch (InterruptedException | ExecutionException | TimeoutException | CandidateAlreadyRegisteredException e) {
- LOG.warn("Unexpected exception by DeviceConection {}. Connection has to close.", deviceContext.getDeviceState().getNodeId(), e);
- final Optional<EntityOwnershipState> entityOwnershipStateOptional = entityOwnershipService.getOwnershipState(roleContext.getEntity());
- if (entityOwnershipStateOptional.isPresent()) {
- // TODO : check again who will call RoleCtx.onRoleChanged but who will call DeviceCtx#onClusterRoleChange
- role = entityOwnershipStateOptional.get().isOwner() ? OfpRole.BECOMEMASTER : OfpRole.BECOMESLAVE;
- } else {
- try {
- deviceContext.close();
- } catch (Exception e1) {
- LOG.warn("Exception during device context close. ", e);
+
+ final ListenableFuture<OfpRole> roleChangeFuture = roleContext.initialization();
+ final ListenableFuture<Void> initDeviceFuture = Futures.transform(roleChangeFuture, new AsyncFunction<OfpRole, Void>() {
+ @Override
+ public ListenableFuture<Void> apply(final OfpRole input) throws Exception {
+ final ListenableFuture<Void> nextFuture;
+ if (OfpRole.BECOMEMASTER.equals(input)) {
+ LOG.debug("Node {} was initialized", deviceContext.getDeviceState().getNodeId());
+ nextFuture = DeviceInitializationUtils.initializeNodeInformation(deviceContext, switchFeaturesMandatory);
+ } else {
+ LOG.debug("Node {} we are not Master so we are going to finish.", deviceContext.getDeviceState().getNodeId());
+ nextFuture = Futures.immediateFuture(null);
}
- return;
+ return nextFuture;
}
- }
- if (OfpRole.BECOMEMASTER.equals(role)) {
- final ListenableFuture<Void> initNodeFuture = DeviceInitializationUtils.initializeNodeInformation(deviceContext, switchFeaturesMandatory);
- Futures.addCallback(initNodeFuture, new FutureCallback<Void>() {
- @Override
- public void onSuccess(final Void result) {
- LOG.trace("Node {} was initialized", deviceContext.getDeviceState().getNodeId());
- getRoleContextLevelUp(deviceContext);
- }
+ });
- @Override
- public void onFailure(final Throwable t) {
- LOG.warn("Node {} Initialization fail", deviceContext.getDeviceState().getNodeId(), t);
- try {
- deviceContext.close();
- } catch (Exception e) {
- LOG.warn("Exception during device context close. ", e);
- }
- }
- });
- } else {
- getRoleContextLevelUp(deviceContext);
- }
+ Futures.addCallback(initDeviceFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ LOG.debug("Initialization Node {} is done.", deviceContext.getDeviceState().getNodeId());
+ getRoleContextLevelUp(deviceContext);
+ }
+ @Override
+ public void onFailure(final Throwable t) {
+ LOG.warn("Unexpected error for Node {} initialization", deviceContext.getDeviceState().getNodeId(), t);
+ deviceContext.close();
+ }
+ });
}
void getRoleContextLevelUp(final DeviceContext deviceContext) {