Adding barrier message support with futures to IOFSwitch driver

Change-Id: I0f2de6c60165c2b6687d647850beb7ce23def83a
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index 6ad24ec..9e1b95a 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -35,7 +35,7 @@
      * Pushes a collection of flows to the switch, at the same time. Can result
      * in better performance, when compared to sending flows one at a time using
      * {@link pushFlow}, especially if the number of flows is large.
-     * 
+     *
      * @param matchActionOps a collection of information required to create a
      *        flowmod
      * @throws IOException
@@ -43,6 +43,7 @@
     public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
             throws IOException;
 
+
     // ****************************
     // Group related
     // ****************************
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
index 7fa7560..fca14a8 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
@@ -27,6 +27,7 @@
 import java.util.concurrent.Future;
 
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
 import net.floodlightcontroller.core.web.serializers.IOFSwitchSerializer;
 import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
@@ -36,6 +37,7 @@
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.jboss.netty.channel.Channel;
 import org.projectfloodlight.openflow.protocol.OFActionType;
+import org.projectfloodlight.openflow.protocol.OFBarrierReply;
 import org.projectfloodlight.openflow.protocol.OFCapabilities;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFFactory;
@@ -114,7 +116,7 @@
      * @return whether the switch is still disconnected
      */
     public boolean isConnected();
-    
+
     /**
      * retun the channelSocket ip address with port number
      * @return channelSocketAddress
@@ -632,8 +634,28 @@
     public void setTableFull(boolean isFull);
 
     /**
-     * Get the switch driver hanshake state
+     * Get the switch driver handshake state
      */
     public String getSwitchDriverState();
 
+    /**
+     * sendBarrier sends an OF Barrier message to the switch and returns a
+     * future object to the caller. The future will automatically deregister
+     * itself after 60 secs if the corresponding barrier reply message is not
+     * received from the switch in that time.
+     * <p>
+     * The caller should use OFBarrierReplyFuture.get(timeout,timeunit) to wait
+     * for a specified time interval shorter than 60secs.
+     *
+     * @throws IOException
+     */
+    public OFBarrierReplyFuture sendBarrier() throws IOException;
+
+    /**
+     * Delivers the barrier future reply.
+     *
+     * @param reply the reply to deliver
+     */
+    public void deliverBarrierReply(OFBarrierReply reply);
+
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFBarrierReplyFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFBarrierReplyFuture.java
new file mode 100644
index 0000000..3de5a7d
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFBarrierReplyFuture.java
@@ -0,0 +1,47 @@
+package net.floodlightcontroller.core.internal;
+
+import java.util.concurrent.TimeUnit;
+
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.threadpool.IThreadPoolService;
+
+import org.projectfloodlight.openflow.protocol.OFBarrierReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
+
+public class OFBarrierReplyFuture extends OFMessageFuture<OFBarrierReply> {
+    protected volatile boolean finished;
+
+    public OFBarrierReplyFuture(IThreadPoolService tp,
+            IOFSwitch sw, int transactionId) {
+        super(tp, sw, OFType.BARRIER_REPLY, transactionId);
+        init();
+    }
+
+    public OFBarrierReplyFuture(IThreadPoolService tp,
+            IOFSwitch sw, int transactionId, long timeout, TimeUnit unit) {
+        super(tp, sw, OFType.BARRIER_REPLY, transactionId, timeout, unit);
+        init();
+    }
+
+    private void init() {
+        this.finished = false;
+        this.result = null;
+    }
+
+    @Override
+    protected void handleReply(IOFSwitch sw, OFMessage msg) {
+        this.result = (OFBarrierReply) msg;
+        this.finished = true;
+    }
+
+    @Override
+    protected boolean isFinished() {
+        return finished;
+    }
+
+    @Override
+    protected void unRegister() {
+        super.unRegister();
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
index b011e6b..e0e0691 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
@@ -1241,6 +1241,7 @@
             @Override
             void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m)
                     throws IOException {
+                h.sw.deliverBarrierReply(m);
                 h.dispatchMessage(m);
             }
 
@@ -1665,6 +1666,9 @@
             if ((h.sw.getRole() == Role.MASTER && role == Role.SLAVE) ||
                     (h.sw.getRole() == Role.MASTER && role == Role.EQUAL)) {
                 // the mastership has changed
+                if (role == Role.SLAVE) {
+                    role = Role.EQUAL;
+                }
                 h.sw.setRole(role);
                 h.setState(EQUAL);
                 h.controller.transitionToEqualSwitch(h.sw.getId());
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
index d92719c..442dd68 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
@@ -60,6 +60,7 @@
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.jboss.netty.channel.Channel;
 import org.projectfloodlight.openflow.protocol.OFActionType;
+import org.projectfloodlight.openflow.protocol.OFBarrierReply;
 import org.projectfloodlight.openflow.protocol.OFCapabilities;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFFactories;
@@ -133,6 +134,7 @@
     // XXX Consider removing the following 2 maps - not used anymore
     protected Map<Integer, IOFMessageListener> iofMsgListenersMap;
     protected Map<Integer, OFFeaturesReplyFuture> featuresFutureMap;
+    protected Map<Long, OFBarrierReplyFuture> barrierFutureMap;
     protected boolean connected;
     protected Role role;
     protected ReentrantReadWriteLock listenerLock;
@@ -209,6 +211,7 @@
         this.statsFutureMap = new ConcurrentHashMap<Integer, OFStatisticsFuture>();
         this.featuresFutureMap = new ConcurrentHashMap<Integer, OFFeaturesReplyFuture>();
         this.iofMsgListenersMap = new ConcurrentHashMap<Integer, IOFMessageListener>();
+        this.barrierFutureMap = new ConcurrentHashMap<Long, OFBarrierReplyFuture>();
         this.role = null;
         this.listenerLock = new ReentrantReadWriteLock();
         this.pendingRoleRequests = new LinkedList<OFSwitchImplBase.PendingRoleRequestEntry>();
@@ -1296,4 +1299,24 @@
         return "";
     }
 
+    public OFBarrierReplyFuture sendBarrier() throws IOException {
+        long xid = getNextTransactionId();
+        OFMessage br = getFactory()
+                .buildBarrierRequest()
+                .setXid(xid)
+                .build();
+        write(Collections.singletonList(br));
+        OFBarrierReplyFuture future = new OFBarrierReplyFuture(threadPool, this,
+                (int) xid);
+        barrierFutureMap.put(xid, future);
+        return future;
+    }
+
+    public void deliverBarrierReply(OFBarrierReply br) {
+        OFBarrierReplyFuture f = barrierFutureMap.get(br.getXid());
+        if (f != null) {
+            f.deliverFuture(this, br);
+            barrierFutureMap.remove(br.getXid());
+        }
+    }
 }
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
index 7162554..0931eca 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
@@ -234,19 +234,19 @@
         case INIT:
             driverState = DriverState.SET_TABLE_MISS_ENTRIES;
             setTableMissEntries();
-            sendBarrier();
+            sendHandshakeBarrier();
             break;
         case SET_TABLE_MISS_ENTRIES:
             driverState = DriverState.SET_TABLE_VLAN_TMAC;
             getNetworkConfig();
             populateTableVlan();
             populateTableTMac();
-            sendBarrier();
+            sendHandshakeBarrier();
             break;
         case SET_TABLE_VLAN_TMAC:
             driverState = DriverState.SET_GROUPS;
             createGroups();
-            sendBarrier();
+            sendHandshakeBarrier();
             break;
         case SET_GROUPS:
             driverState = DriverState.VERIFY_GROUPS;
@@ -378,7 +378,7 @@
         populateTableMissEntry(TABLE_ACL, false, false, false, -1);
     }
 
-    private void sendBarrier() throws IOException {
+    private void sendHandshakeBarrier() throws IOException {
         long xid = getNextTransactionId();
         barrierXidToWaitFor = xid;
         OFBarrierRequest br = getFactory()
@@ -1145,7 +1145,7 @@
         // getTableFeatures();
         sendGroupFeaturesRequest();
         setL2Groups();
-        sendBarrier();
+        sendHandshakeBarrier();
         setL3Groups();
         setL25Groups();
         // setEcmpGroup();
@@ -1155,7 +1155,7 @@
         populateIpTable();
         populateMplsTable();
         populateTableMissEntry(TABLE_ACL, false, false, false, -1);
-        sendBarrier();
+        sendHandshakeBarrier();
     }
 
     private void setAsyncConfig() throws IOException {