From 6efcb2ef0e9d658f21da2fa93d88b231cb92db2a Mon Sep 17 00:00:00 2001
From: Shudong Zhou <shudongzhou@gmail.com>
Date: Wed, 30 Jan 2013 20:33:51 -0800
Subject: [PATCH] Dampen frequency of HA role transitions

---
 .../core/internal/Controller.java             | 27 ++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index ee74d3d7f..ae7f478f7 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();
+            }
+        });
     }
 
     /**
-- 
GitLab