diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index ee74d3d7f201c0e62290b3b88ddb7fd081f57648..ae7f478f74b98dfc6e8ea322c13c1ea5afb79326 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -41,6 +41,8 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; @@ -57,6 +59,7 @@ import net.floodlightcontroller.core.annotations.LogMessageDoc; import net.floodlightcontroller.core.annotations.LogMessageDocs; import net.floodlightcontroller.core.internal.OFChannelState.HandshakeState; import net.floodlightcontroller.core.util.ListenerDispatcher; +import net.floodlightcontroller.core.util.SingletonTask; import net.floodlightcontroller.core.web.CoreWebRoutable; import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.flowcache.IFlowCacheService; @@ -186,9 +189,12 @@ public class Controller implements IFloodlightProviderService, // this role and then notify, on a transition to master we first notify // and then set the role. We then use it to make sure we don't forward // OF messages while the modules are in slave role. - protected volatile Role notifiedRole; + // The pendingRole is a role change just received, but not sent out + // notifications yet. + protected Role pendingRole;protected volatile Role notifiedRole; // A helper that handles sending and timeout handling for role requests protected RoleChanger roleChanger; + protected SingletonTask roleChangeDamper; // Start time of the controller protected long systemStartTime; @@ -382,19 +388,26 @@ public class Controller implements IFloodlightProviderService, public void setRole(Role role) { if (role == null) throw new NullPointerException("Role can not be null."); + // If role is changed in quick succession for some reason, + // the 2 second delay will dampen the frequency. + this.pendingRole = role; + roleChangeDamper.reschedule(2000, TimeUnit.MILLISECONDS); + } + + protected void doSetRole() { // Need to synchronize to ensure a reliable ordering on role request // messages send and to ensure the list of connected switches is stable // RoleChanger will handle the actual sending of the message and // timeout handling // @see RoleChanger synchronized(roleChanger) { - if (role.equals(this.role)) { + if (pendingRole.equals(this.role)) { log.debug("Ignoring role change: role is already {}", role); return; } Role oldRole = this.role; - this.role = role; + this.role = pendingRole; log.debug("Submitting role change request to role {}", role); roleChanger.submitRequest(connectedSwitches, role); @@ -1768,6 +1781,14 @@ public class Controller implements IFloodlightProviderService, this.roleChanger = new RoleChanger(this); initVendorMessages(); this.systemStartTime = System.currentTimeMillis(); + + ScheduledExecutorService ses = threadPool.getScheduledExecutor(); + roleChangeDamper = new SingletonTask(ses, new Runnable() { + @Override + public void run() { + doSetRole(); + } + }); } /**