X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Frole%2FRoleContextImpl.java;h=5ddf504fbb066de0a50927683df0f363e042e2c9;hb=d10c556113e37e0cb9fa08ed47932f72ba454ee3;hp=fc813f5ee1c495d1b066ff2c61157985f4fbbf16;hpb=a61fc32d8a1c0006fe823694f159b98a8269702c;p=openflowplugin.git diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java index fc813f5ee1..5ddf504fbb 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java @@ -7,238 +7,196 @@ */ package org.opendaylight.openflowplugin.impl.role; -import javax.annotation.Nullable; -import java.util.concurrent.Future; - -import com.google.common.annotations.VisibleForTesting; 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.Futures; -import com.google.common.util.concurrent.JdkFutureAdapters; -import com.google.common.util.concurrent.ListenableFuture; -import java.util.concurrent.Future; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; import javax.annotation.Nullable; 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.EntityOwnershipCandidateRegistration; import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; -import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; -import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; -import org.opendaylight.openflowplugin.api.openflow.device.DeviceState; +import org.opendaylight.openflowplugin.api.openflow.OFPContext; +import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; +import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor; import org.opendaylight.openflowplugin.api.openflow.role.RoleContext; import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext; -import org.opendaylight.openflowplugin.impl.services.SalRoleServiceImpl; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole; import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput; -import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Created by kramesha on 9/12/15. + * Role context hold information about entity ownership registration, + * register and unregister candidate (main and tx) */ -public class RoleContextImpl implements RoleContext { +class RoleContextImpl implements RoleContext { + private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class); + private static final int TIMEOUT = 12; + private final DeviceInfo deviceInfo; private final EntityOwnershipService entityOwnershipService; - private EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration; - private final DeviceContext deviceContext; - private final Entity entity; - private SalRoleService salRoleService; + private volatile EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration = null; + private volatile EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration = null; - private EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration; + private final Entity entity; private final Entity txEntity; - private final Semaphore mainCandidateGuard = new Semaphore(1, true); - private final Semaphore txCandidateGuard = new Semaphore(1, true); - private volatile ROLE_CONTEXT_STATE state; - private volatile boolean txLockOwned; - private volatile OfpRole propagatingRole; + private SalRoleService salRoleService = null; - public RoleContextImpl(final DeviceContext deviceContext, final EntityOwnershipService entityOwnershipService, - final Entity entity, final Entity txEnitity) { - this.entityOwnershipService = Preconditions.checkNotNull(entityOwnershipService); - this.deviceContext = Preconditions.checkNotNull(deviceContext); - this.entity = Preconditions.checkNotNull(entity); - this.txEntity = Preconditions.checkNotNull(txEnitity); - - salRoleService = new SalRoleServiceImpl(this, deviceContext); - } - - @Override - public void initialization() throws CandidateAlreadyRegisteredException { - state = ROLE_CONTEXT_STATE.STARTING; - LOG.debug("Initialization requestOpenflowEntityOwnership for entity {}", entity); - entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity); - LOG.debug("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext - .getPrimaryConnectionContext().getNodeId().getValue()); - } + private final Semaphore roleChangeGuard = new Semaphore(1, true); - @Override - public ListenableFuture 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()); - LOG.debug("SetRole cancelled for entity [{}], reason = device disconnected.", entity); - return Futures.immediateFailedFuture(new Exception( - "Device disconnected - stopped by setRole: " + deviceContext - .getPrimaryConnectionContext().getNodeId())); - } + private final LifecycleConductor conductor; + private volatile CONTEXT_STATE contextState; - LOG.debug("Role change received from ownership listener from {} to {} for device:{}", oldRole, newRole, - deviceContext.getPrimaryConnectionContext().getNodeId()); - - final SetRoleInput setRoleInput = (new SetRoleInputBuilder()) - .setControllerRole(newRole) - .setNode(new NodeRef(deviceContext.getDeviceState().getNodeInstanceIdentifier())) - .build(); - - final Future> setRoleOutputFuture = salRoleService.setRole(setRoleInput); - - return Futures.transform(JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture), - new AsyncFunction, Void>() { - @Override - public ListenableFuture apply(final RpcResult setRoleOutputRpcResult) throws Exception { - LOG.debug("Rolechange {} successful made on switch :{}", newRole, deviceContext.getDeviceState().getNodeId()); - final ListenableFuture nextStepFuture; - switch (state) { - case STARTING: - if (OfpRole.BECOMESLAVE.equals(newRole)) { - getDeviceState().setRole(newRole); - nextStepFuture = Futures.immediateFuture(null); - } else if (OfpRole.BECOMEMASTER.equals(newRole)) { - nextStepFuture = deviceContext.onClusterRoleChange(newRole); - } else { - nextStepFuture = Futures.immediateFuture(null); - } - - break; - case WORKING: - nextStepFuture = deviceContext.onClusterRoleChange(newRole); - break; - //case TEARING_DOWN: - default: - nextStepFuture = Futures.immediateFuture(null); - break; - } - - return nextStepFuture; - } - }); + RoleContextImpl(final DeviceInfo deviceInfo, final EntityOwnershipService entityOwnershipService, final Entity entity, final Entity txEntity, final LifecycleConductor lifecycleConductor) { + this.entityOwnershipService = entityOwnershipService; + this.entity = entity; + this.txEntity = txEntity; + this.deviceInfo = deviceInfo; + this.conductor = lifecycleConductor; + contextState = CONTEXT_STATE.INITIALIZATION; } @Override - public void setupTxCandidate() throws CandidateAlreadyRegisteredException { - LOG.debug("setupTxCandidate for entity {} and Transaction entity {}", entity, txEntity); - Verify.verify(txEntity != null); - - txEntityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(txEntity); + public boolean initialization() { + LOG.info("Initialization main candidate for node {}", deviceInfo.getNodeId()); + contextState = CONTEXT_STATE.WORKING; + return registerCandidate(this.entity); } @Override - public void close() { - if (entityOwnershipCandidateRegistration != null) { - LOG.debug("Closing EntityOwnershipCandidateRegistration for {}", entity); - entityOwnershipCandidateRegistration.close(); + public void unregisterAllCandidates() { + LOG.info("Role context closed, unregistering all candidates for ownership for node {}", deviceInfo.getNodeId()); + if (isMainCandidateRegistered()) { + unregisterCandidate(this.entity); + } + if (isTxCandidateRegistered()) { + unregisterCandidate(this.txEntity); } - } - - @Override - public Entity getEntity() { - return entity; - } - - @Override - public Entity getTxEntity() { - return txEntity; - } - - private boolean isDeviceConnected() { - return ConnectionContext.CONNECTION_STATE.WORKING.equals( - deviceContext.getPrimaryConnectionContext().getConnectionState()); } @Nullable @Override public RequestContext createRequestContext() { - final AbstractRequestContext ret = new AbstractRequestContext(deviceContext.getReservedXid()) { + return new AbstractRequestContext(conductor.reserveXidForDeviceMessage(deviceInfo)) { @Override public void close() { } }; - return ret; } - @VisibleForTesting - void setSalRoleService(final SalRoleService salRoleService) { + @Override + public void setSalRoleService(@Nonnull final SalRoleService salRoleService) { + Preconditions.checkNotNull(salRoleService); this.salRoleService = salRoleService; } @Override - public DeviceState getDeviceState() { - return deviceContext.getDeviceState(); + public SalRoleService getSalRoleService() { + return this.salRoleService; } @Override - public void suspendTxCandidate() { - if (txEntityOwnershipCandidateRegistration != null) { - txEntityOwnershipCandidateRegistration.close(); - txEntityOwnershipCandidateRegistration = null; - } + public Entity getEntity() { + return this.entity; } @Override - public DeviceContext getDeviceContext() { - return deviceContext; + public Entity getTxEntity() { + return this.txEntity; } @Override - public Semaphore getMainCandidateGuard() { - return mainCandidateGuard; + public DeviceInfo getDeviceInfo() { + return deviceInfo; } @Override - public Semaphore getTxCandidateGuard() { - return txCandidateGuard; + public boolean isMainCandidateRegistered() { + return entityOwnershipCandidateRegistration != null; } @Override - public ROLE_CONTEXT_STATE getState() { - return state; + public boolean isTxCandidateRegistered() { + return txEntityOwnershipCandidateRegistration != null; } @Override - public boolean isTxLockOwned() { - return txLockOwned; + public boolean registerCandidate(final Entity entity_) { + boolean permit = false; + try { + permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS); + if(permit) { + LOG.debug("Register candidate for entity {}", entity_); + if (entity_.equals(this.entity)) { + entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_); + } else { + txEntityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_); + } + } else { + return false; + } + } catch (final CandidateAlreadyRegisteredException e) { + LOG.warn("Candidate for entity {} is already registered.", entity_.getType()); + return false; + } catch (final InterruptedException e) { + LOG.warn("Cannot acquire semaphore for register entity {} candidate.", entity_.getType()); + return false; + } finally { + if (permit) { + roleChangeGuard.release(); + } + } + return true; } @Override - public void setTxLockOwned(final boolean txLockOwned) { - this.txLockOwned = txLockOwned; + public boolean unregisterCandidate(final Entity entity_) { + boolean permit = false; + try { + permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS); + if(permit) { + if (entity_.equals(this.entity)) { + if (entityOwnershipCandidateRegistration != null) { + LOG.debug("Unregister candidate for entity {}", entity_); + entityOwnershipCandidateRegistration.close(); + entityOwnershipCandidateRegistration = null; + } + } else { + if (txEntityOwnershipCandidateRegistration != null) { + LOG.debug("Unregister candidate for tx entity {}", entity_); + txEntityOwnershipCandidateRegistration.close(); + txEntityOwnershipCandidateRegistration = null; + } + } + } else { + return false; + } + } catch (final InterruptedException e) { + LOG.warn("Cannot acquire semaphore for unregister entity {} candidate.", entity_.getType()); + return false; + } finally { + if (permit) { + roleChangeGuard.release(); + } + } + return true; } @Override - public void promoteStateToWorking() { - state = ROLE_CONTEXT_STATE.WORKING; + public void close() { + contextState = CONTEXT_STATE.TERMINATION; + unregisterAllCandidates(); } - @Override - public OfpRole getPropagatingRole() { - return propagatingRole; + public boolean isMaster(){ + return (txEntityOwnershipCandidateRegistration != null && entityOwnershipCandidateRegistration != null); } @Override - public void setPropagatingRole(final OfpRole propagatingRole) { - this.propagatingRole = propagatingRole; + public CONTEXT_STATE getState() { + return contextState; } }