Added more switch/controller registry APIs and curator implementations
diff --git a/mastership-test.sh b/mastership-test.sh
index 06189df..06907f0 100755
--- a/mastership-test.sh
+++ b/mastership-test.sh
@@ -1 +1 @@
-java -Dlogback.configurationFile=logback.xml -cp target/floodlight-only.jar:lib/*:lib/titan/* net.floodlightcontroller.mastership.MastershipManager $1
+java -Dlogback.configurationFile=logback.xml -cp target/floodlight-only.jar:lib/*:lib/titan/* net.floodlightcontroller.mastership.MastershipRunner $1
diff --git a/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java b/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
index 83800c3..fdcb5c0 100644
--- a/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
+++ b/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
@@ -1,7 +1,10 @@
 package net.floodlightcontroller.mastership;
 
+import java.util.Collection;
+
 import net.floodlightcontroller.core.module.IFloodlightService;
 
+//Will change to something like IRegistryService
 public interface IMastershipService extends IFloodlightService {
 	
 	// Callback for all mastership changes. 
@@ -24,4 +27,21 @@
 	public void setMastershipId (String id);
 	public String getMastershipId ();
 	
+	/**
+	 * Register a controller to the ONOS cluster
+	 * @param controller A string identifying the controller and (possibly) how to talk to it.
+	 * (We will have to develop a convention for this - most likely hostname:port)
+	 */
+	public void registerController(String controllerId);
+	
+	/**
+	 * Get all controllers in the cluster
+	 * @return
+	 */
+	public Collection<String> getAllControllers();
+	
+	
+	public String getControllerForSwitch(long dpid);
+	
+	public Collection<Long> getSwitchesControlledByController(String controllerId);
 }
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java b/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
index 46b533e..f4230ae 100644
--- a/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
@@ -1,10 +1,12 @@
 package net.floodlightcontroller.mastership;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
@@ -12,6 +14,7 @@
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 
+import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher.Event.KeeperState;
 import org.openflow.util.HexString;
@@ -22,6 +25,9 @@
 import com.netflix.curator.framework.CuratorFramework;
 import com.netflix.curator.framework.CuratorFrameworkFactory;
 import com.netflix.curator.framework.api.CuratorWatcher;
+import com.netflix.curator.framework.recipes.cache.ChildData;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
 import com.netflix.curator.framework.recipes.leader.LeaderLatch;
 import com.netflix.curator.framework.recipes.leader.Participant;
 import com.netflix.curator.retry.ExponentialBackoffRetry;
@@ -34,9 +40,12 @@
 	//TODO read this from configuration
 	protected String connectionString = "localhost:2181";
 	private final String namespace = "onos";
-	private final String switchLatchesPath = "/switchmastership";
+	private final String switchLatchesPath = "/switches";
 	
 	protected CuratorFramework client;
+	
+	private final String controllerPath = "/controllers";
+	protected PathChildrenCache controllerCache;
 
 	protected Map<String, LeaderLatch> switchLatches;
 	protected Map<String, MastershipCallback> switchCallbacks;
@@ -52,7 +61,7 @@
 		}
 		
 		@Override
-		public void process(WatchedEvent event) throws Exception {
+		public synchronized void process(WatchedEvent event) throws Exception {
 			log.debug("Watch Event: {}", event);
 
 			LeaderLatch latch = switchLatches.get(dpid);
@@ -68,6 +77,7 @@
 			}
 			
 			try {
+				
 				Participant leader = latch.getLeader();
 
 				if (leader.getId().equals(mastershipId) && !isLeader){
@@ -96,6 +106,7 @@
 			//client.getChildren().usingWatcher(this).forPath(latchPath);
 		}
 	}
+
 	
 	@Override
 	public void acquireMastership(long dpid, MastershipCallback cb) throws Exception {
@@ -176,6 +187,83 @@
 		return mastershipId;
 	}
 	
+	@Override
+	public Collection<String> getAllControllers() {
+		// TODO Auto-generated method stub
+		log.debug("Getting all controllers");
+		List<String> controllers = new ArrayList<String>();
+		for (ChildData data : controllerCache.getCurrentData()){
+
+			String d = null;
+			try {
+				d = new String(data.getData(), "UTF-8");
+			} catch (UnsupportedEncodingException e) {
+				// TODO unlikely(throw exception)
+				e.printStackTrace();
+			}
+
+			controllers.add(d);
+		}
+		return controllers;
+	}
+
+	@Override
+	public void registerController(String id) {
+		// TODO Auto-generated method stub
+		byte bytes[] = null;
+		try {
+			bytes = id.getBytes("UTF-8");
+		} catch (UnsupportedEncodingException e1) {
+			// TODO Throw some exception (very unlikely this will happen)
+			e1.printStackTrace();
+		}
+		
+		String path = controllerPath + "/" + id;
+		
+		log.info("Registering controller with id {}", id);
+		
+		//Create ephemeral node with my id
+		try {
+			client.create().withProtection().withMode(CreateMode.EPHEMERAL)
+					.forPath(path, bytes);
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			// TODO Make an exception that will be thrown here
+			e.printStackTrace();
+		}
+	}
+	
+	@Override
+	public String getControllerForSwitch(long dpid) {
+		// TODO Work out how we should store this controller/switch data.
+		// The leader latch might be a index to the /controllers collections
+		// which holds more info on the controller (how to talk to it for example).
+		
+		
+		String strDpid = HexString.toHexString(dpid);
+		LeaderLatch latch = switchLatches.get(strDpid);
+		
+		if (latch == null){
+			log.warn("Tried to get controller for non-existent switch");
+			return null;
+		}
+		
+		Participant leader = null;
+		try {
+			leader = latch.getLeader();
+		} catch (Exception e) {
+			// TODO Zookeeper issue, throw exception
+			e.printStackTrace();
+		}
+		
+		return leader.getId();
+	}
+	
+	@Override
+	public Collection<Long> getSwitchesControlledByController(String controllerId) {
+		// TODO Auto-generated method stub
+		return null;
+	}
 	
 	/*
 	 * IFloodlightModule
@@ -183,7 +271,8 @@
 	
 	@Override
 	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-		Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+		Collection<Class<? extends IFloodlightService>> l = 
+				new ArrayList<Class<? extends IFloodlightService>>();
 		l.add(IMastershipService.class);
 		return l;
 	}
@@ -224,58 +313,21 @@
 		
 		client = client.usingNamespace(namespace);
 		
-		return;
+		controllerCache = new PathChildrenCache(client, controllerPath, true);
+		
+		try {
+			controllerCache.start(StartMode.BUILD_INITIAL_CACHE);
+			
+			
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
 	}
 	
 	@Override
 	public void startUp (FloodlightModuleContext context) {
 		// Nothing to be done on startup
 	}
-	
-	public static void main(String args[]){
-		FloodlightModuleContext fmc = new FloodlightModuleContext();
-		MastershipManager mm = new MastershipManager();
-		
-		String id = null;
-		if (args.length > 0){
-			id = args[0];
-			log.info("Using unique id: {}", id);
-		}
-		
-		try {
-			mm.init(fmc);
-			mm.startUp(fmc);
-			
-			if (id != null){
-				mm.setMastershipId(id);
-			}
-				
-			mm.acquireMastership(1L, 
-				new MastershipCallback(){
-					@Override
-					public void changeCallback(long dpid, boolean isMaster) {
-						if (isMaster){
-							log.debug("Callback for becoming master for {}", HexString.toHexString(dpid));
-						}
-						else {
-							log.debug("Callback for losing mastership for {}", HexString.toHexString(dpid));
-						}
-					}
-				});
-			
-			//"Server" loop
-			while (true) {
-				Thread.sleep(60000);
-			}
-			
-		} catch (FloodlightModuleException e) {
-			e.printStackTrace();
-		} catch (InterruptedException e) {
-			e.printStackTrace();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-		
-		log.debug("is master: {}", mm.amMaster(1L));
-	}
 }
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipRunner.java b/src/main/java/net/floodlightcontroller/mastership/MastershipRunner.java
new file mode 100644
index 0000000..a28a9c5
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipRunner.java
@@ -0,0 +1,70 @@
+package net.floodlightcontroller.mastership;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.mastership.IMastershipService.MastershipCallback;
+
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Used for lightweight testing of the mastership module without having
+ * to load up the entire ONOS.
+ * @author jono
+ *
+ */
+public class MastershipRunner {
+	protected static Logger log = LoggerFactory.getLogger(MastershipRunner.class);
+
+	public static void main(String args[]){
+		FloodlightModuleContext fmc = new FloodlightModuleContext();
+		MastershipManager mm = new MastershipManager();
+		
+		String id = null;
+		if (args.length > 0){
+			id = args[0];
+			log.info("Using unique id: {}", id);
+		}
+		
+		try {
+			mm.init(fmc);
+			mm.startUp(fmc);
+			
+			if (id != null){
+				mm.setMastershipId(id);
+			}
+				
+			mm.acquireMastership(1L, 
+				new MastershipCallback(){
+					@Override
+					public void changeCallback(long dpid, boolean isMaster) {
+						if (isMaster){
+							log.debug("Callback for becoming master for {}", HexString.toHexString(dpid));
+						}
+						else {
+							log.debug("Callback for losing mastership for {}", HexString.toHexString(dpid));
+						}
+					}
+				});
+			
+			mm.registerController(id);
+			
+			Thread.sleep(5000);
+			
+			//"Server" loop
+			while (true) {
+				Thread.sleep(60000);
+			}
+			
+		} catch (FloodlightModuleException e) {
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		
+		log.debug("is master: {}", mm.amMaster(1L));
+	}
+}