switch can now connect
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
index 7f4830d..534daa0 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
@@ -18,7 +18,9 @@
 package org.onlab.onos.of.controller.impl.internal;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.jboss.netty.channel.Channel;
 import org.onlab.onos.of.controller.Dpid;
@@ -27,12 +29,14 @@
 import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
 import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleRecvStatus;
 import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleReplyInfo;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFErrorMsg;
 import org.projectfloodlight.openflow.protocol.OFExperimenter;
 import org.projectfloodlight.openflow.protocol.OFFactories;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
 import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFRoleReply;
 import org.projectfloodlight.openflow.protocol.OFVersion;
@@ -45,10 +49,13 @@
     private static Logger log =
             LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
 
-    private Channel channel;
+    protected Channel channel;
+    protected boolean startDriverHandshakeCalled = false;
+
     private boolean connected;
     private Dpid dpid;
     private OpenFlowSwitchAgent agent;
+    private AtomicInteger xidCounter = new AtomicInteger(0);
 
     private OFVersion ofVersion;
 
@@ -58,8 +65,12 @@
 
     private final RoleManager roleMan = new RoleManager(this);
 
-    protected AbstractOpenFlowSwitch(long dpid) {
-        this.dpid = new Dpid(dpid);
+    protected RoleState role;
+
+    protected OFFeaturesReply features;
+
+    protected AbstractOpenFlowSwitch(Dpid dp) {
+        this.dpid = dp;
     }
 
     //************************
@@ -80,14 +91,16 @@
      *
      * @param m the message to be written
      */
-    public abstract void write(OFMessage m);
+    public abstract void sendMsg(OFMessage m);
 
     /**
      * Writes to the OFMessage list to the output stream.
      *
      * @param msgs the messages to be written
      */
-    public abstract void write(List<OFMessage> msgs);
+    public void write(List<OFMessage> msgs) {
+        this.channel.write(msgs);
+    }
 
 
     /**
@@ -151,7 +164,9 @@
         this.tableFull = full;
     }
 
-    public abstract void setFeaturesReply(OFFeaturesReply featuresReply);
+    public void setFeaturesReply(OFFeaturesReply featuresReply) {
+        this.features = featuresReply;
+    }
 
     /**
      * Let peoeple know if you support Nicira style role requests.
@@ -172,7 +187,9 @@
         this.agent.processMessage(m);
     }
 
-    public abstract RoleState getRole();
+    public RoleState getRole() {
+        return role;
+    };
 
     final boolean addConnectedSwitch() {
         return this.agent.addConnectedSwitch(this.getId(), this);
@@ -214,7 +231,9 @@
 
     public void setRole(RoleState role) {
         try {
-            this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE);
+            if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
+                this.role = role;
+            }
         } catch (IOException e) {
            log.error("Unable to write to switch {}.", this.dpid);
         }
@@ -236,23 +255,23 @@
     }
 
     void handleNiciraRole(OFMessage m) throws SwitchStateException {
-        RoleState role = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
-      if (role == null) {
-          // The message wasn't really a Nicira role reply. We just
-          // dispatch it to the OFMessage listeners in this case.
-          this.handleMessage(m);
-      }
+        RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
+        if (r == null) {
+            // The message wasn't really a Nicira role reply. We just
+            // dispatch it to the OFMessage listeners in this case.
+            this.handleMessage(m);
+        }
 
-      RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
-              new RoleReplyInfo(role, null, m.getXid()));
-          if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-              if (role == RoleState.MASTER) {
-                  this.transitionToMasterSwitch();
-              } else if (role == RoleState.EQUAL ||
-                      role == RoleState.SLAVE) {
-                  this.transitionToEqualSwitch();
-              }
-          }
+        RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
+                new RoleReplyInfo(r, null, m.getXid()));
+        if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+            if (r == RoleState.MASTER) {
+                this.transitionToMasterSwitch();
+            } else if (r == RoleState.EQUAL ||
+                    r == RoleState.SLAVE) {
+                this.transitionToEqualSwitch();
+            }
+        }
     }
 
     boolean handleRoleError(OFErrorMsg error) {
@@ -274,6 +293,16 @@
         this.agent = ag;
     }
 
+    public void setSwitchDescription(OFDescStatsReply desc) {
+        // TODO Auto-generated method stub
+    }
 
+    protected int getNextTransactionId() {
+        return this.xidCounter.getAndIncrement();
+    }
+
+    protected List<OFPortDesc> getPorts() {
+        return Collections.unmodifiableList(ports.getEntries());
+    }
 
 }
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
index 6ae3abb..b88a9ec 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
@@ -29,9 +29,11 @@
 import org.jboss.netty.channel.group.ChannelGroup;
 import org.jboss.netty.channel.group.DefaultChannelGroup;
 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.onlab.onos.of.controller.Dpid;
 import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
 import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
 import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
+import org.onlab.onos.of.drivers.DriverManager;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFFactories;
 import org.projectfloodlight.openflow.protocol.OFFactory;
@@ -83,11 +85,6 @@
     // Getters/Setters
     // ***************
 
-
-    public synchronized void setIOFSwitchManager(IOFSwitchManager swManager) {
-        this.switchManager = swManager;
-    }
-
     public OFFactory getOFMessageFactory10() {
         return FACTORY10;
     }
@@ -201,18 +198,6 @@
 
     }
 
-    /**
-     * Startup all of the controller's components.
-     */
-    @LogMessageDoc(message = "Waiting for storage source",
-            explanation = "The system database is not yet ready",
-            recommendation = "If this message persists, this indicates " +
-                    "that the system database has failed to start. " +
-                    LogMessageDoc.CHECK_CONTROLLER)
-    public synchronized void startupComponents() {
-        //TODO do something maybe
-    }
-
     // **************
     // Utility methods
     // **************
@@ -236,9 +221,10 @@
      * @param desc
      * @return switch instance
      */
-    protected AbstractOpenFlowSwitch getOFSwitchInstance(OFDescStatsReply desc, OFVersion ofv) {
-        AbstractOpenFlowSwitch sw =  switchManager.getSwitchImpl(desc.getMfrDesc(), desc.getHwDesc(),
-                                            desc.getSwDesc(), ofv);
+    protected AbstractOpenFlowSwitch getOFSwitchInstance(long dpid,
+            OFDescStatsReply desc, OFVersion ofv) {
+        AbstractOpenFlowSwitch sw = DriverManager.getOFSwitchImpl(new Dpid(dpid),
+                desc, ofv);
         sw.setAgent(agent);
         return sw;
     }
@@ -247,7 +233,6 @@
         log.info("Initialising OpenFlow Lib and IO");
         this.agent = ag;
         this.init(new HashMap<String, String>());
-        this.startupComponents();
         this.run();
     }
 
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
index 5db1fc3..f4185e8 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
@@ -230,12 +230,6 @@
                 h.thisdpid = m.getDatapathId().getLong();
                 log.info("Received features reply for switch at {} with dpid {}",
                         h.getSwitchInfoString(), h.thisdpid);
-                //update the controller about this connected switch
-                boolean success = h.sw.addConnectedSwitch();
-                if (!success) {
-                    disconnectDuplicate(h);
-                    return;
-                }
 
                 h.featuresReply = m; //temp store
                 if (h.ofVersion == OFVersion.OF_10) {
@@ -419,7 +413,12 @@
                         h.channel.getRemoteAddress());
                 OFDescStatsReply drep = (OFDescStatsReply) m;
                 // Here is where we differentiate between different kinds of switches
-                h.sw = h.controller.getOFSwitchInstance(drep, h.ofVersion);
+                h.sw = h.controller.getOFSwitchInstance(h.thisdpid, drep, h.ofVersion);
+                boolean success = h.sw.addConnectedSwitch();
+                if (!success) {
+                    disconnectDuplicate(h);
+                    return;
+                }
                 // set switch information
                 h.sw.setOFVersion(h.ofVersion);
                 h.sw.setFeaturesReply(h.featuresReply);
@@ -433,7 +432,9 @@
                 //Put switch in EQUAL mode until we hear back from the global registry
                 log.debug("Setting new switch {} to EQUAL and sending Role request",
                         h.sw.getStringId());
-                h.setSwitchRole(RoleState.EQUAL);
+                h.sw.addActivatedEqualSwitch();
+                //h.setSwitchRole(RoleState.EQUAL);
+                h.setSwitchRole(RoleState.MASTER);
                 h.sw.startDriverHandshake();
                 h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
 
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
index 976e347..f846e65 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
@@ -24,12 +24,19 @@
 @Service
 public class OpenFlowControllerImpl implements OpenFlowController {
 
-    protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches;
-    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches;
-    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches;
+    private static final Logger log =
+            LoggerFactory.getLogger(OpenFlowControllerImpl.class);
+
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches =
+            new ConcurrentHashMap<Long, OpenFlowSwitch>();
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches =
+            new ConcurrentHashMap<Long, OpenFlowSwitch>();
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches =
+            new ConcurrentHashMap<Long, OpenFlowSwitch>();
 
     protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
-    protected ArrayList<OpenFlowSwitchListener> ofEventListener;
+    protected ArrayList<OpenFlowSwitchListener> ofEventListener =
+            new ArrayList<OpenFlowSwitchListener>();
 
     private final Controller ctrl = new Controller();
 
@@ -98,29 +105,17 @@
 
     @Override
     public void write(Dpid dpid, OFMessage msg) {
-        this.getSwitch(dpid).write(msg);
+        this.getSwitch(dpid).sendMsg(msg);
     }
 
     @Override
     public void processPacket(OFMessage msg) {
+        log.info("Got message {}", msg);
     }
 
     @Override
     public void setRole(Dpid dpid, RoleState role) {
-        switch (role) {
-        case MASTER:
-            agent.transitionToMasterSwitch(dpid.value());
-            break;
-        case EQUAL:
-            agent.transitionToEqualSwitch(dpid.value());
-            break;
-        case SLAVE:
-            //agent.transitionToSlaveSwitch(dpid.value());
-            break;
-        default:
-            //WTF role is this?
-        }
-
+        ((AbstractOpenFlowSwitch) getSwitch(dpid)).setRole(role);
     }
 
     public class OpenFlowSwitchAgent {
@@ -189,6 +184,7 @@
                         return false;
                     }
                     activeEqualSwitches.put(dpid, sw);
+                    log.info("Added Activated EQUAL Switch {}", dpid);
                     return true;
             } finally {
                 switchLock.unlock();
@@ -203,6 +199,9 @@
         protected void transitionToMasterSwitch(long dpid) {
             switchLock.lock();
             try {
+                if (activeMasterSwitches.containsKey(dpid)) {
+                    return;
+                }
                 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
                 if (sw == null) {
                     log.error("Transition to master called on sw {}, but switch "
@@ -224,6 +223,9 @@
         protected void transitionToEqualSwitch(long dpid) {
             switchLock.lock();
             try {
+                if (activeEqualSwitches.containsKey(dpid)) {
+                    return;
+                }
                 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
                 if (sw == null) {
                     log.error("Transition to equal called on sw {}, but switch "
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
index f31487a..50e7b33 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
@@ -2,7 +2,6 @@
 
 import java.io.IOException;
 import java.util.Collections;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import org.onlab.onos.of.controller.RoleState;
 import org.projectfloodlight.openflow.protocol.OFControllerRole;
@@ -50,7 +49,6 @@
 
     // the expectation set by the caller for the returned role
     private RoleRecvStatus expectation;
-    private AtomicInteger xidCounter;
     private AbstractOpenFlowSwitch sw;
 
 
@@ -58,7 +56,6 @@
         this.requestPending = false;
         this.pendingXid = -1;
         this.pendingRole = null;
-        this.xidCounter = new AtomicInteger(0);
         this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE;
         this.sw = sw;
     }
@@ -85,7 +82,7 @@
             roleToSend = OFNiciraControllerRole.ROLE_SLAVE;
             log.warn("Sending Nx Role.SLAVE to switch {}.", sw);
         }
-        int xid = xidCounter.getAndIncrement();
+        int xid = sw.getNextTransactionId();
         OFExperimenter roleRequest = OFFactories.getFactory(OFVersion.OF_10)
                 .buildNiciraControllerRoleRequest()
                 .setXid(xid)
@@ -113,7 +110,7 @@
                     + " Should only be used for queries.", sw);
         }
 
-        int xid = xidCounter.getAndIncrement();
+        int xid = sw.getNextTransactionId();
         OFRoleRequest rrm = OFFactories.getFactory(OFVersion.OF_13)
                 .buildRoleRequest()
                 .setRole(roleToSend)
@@ -121,7 +118,7 @@
                 //FIXME fix below when we actually use generation ids
                 .setGenerationId(U64.ZERO)
                 .build();
-        sw.write(rrm);
+        sw.sendMsg(rrm);
         return xid;
     }