Merge branch 'master' into ons-rel-rc3

Conflicts:
	scripts/iperf
diff --git a/scripts/cleanup-cassandra.sh b/scripts/cleanup-cassandra.sh
index a88ae6a..4553fd1 100755
--- a/scripts/cleanup-cassandra.sh
+++ b/scripts/cleanup-cassandra.sh
@@ -1,3 +1,3 @@
 #! /bin/bash
 DIR=~/ONOS
-~/titan-0.2.0/bin/gremlin.sh -e $DIR/scripts/cleanup-onos-db 
+~/ONOS/titan/gremlin.sh -e $DIR/scripts/cleanup-onos-db 
diff --git a/scripts/cleanup-onos-db b/scripts/cleanup-onos-db
index 8949fea..1725051 100644
--- a/scripts/cleanup-onos-db
+++ b/scripts/cleanup-onos-db
@@ -1,4 +1,5 @@
 g=TitanFactory.open('/tmp/cassandra.titan')
+g.V('type','device').each{g.removeVertex(it)}
 g.V('type','port').each{g.removeVertex(it)}
 g.V('type','switch').each{g.removeVertex(it)}
 g.V('type','flow').each{g.removeVertex(it)}
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
index 19addad..e29e8e1 100644
--- a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
+++ b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
@@ -45,7 +45,8 @@
 		@Adjacency(label="on")
 		public Iterable<IPortObject> getPorts();
 		
-		@Adjacency(label="on")
+		@JsonIgnore
+		@GremlinGroovy("_().out('on').has('number',port_num)")
 		public IPortObject getPort(final short port_num);
 		
 		@Adjacency(label="on")
@@ -80,7 +81,7 @@
 		public void setDesc(String s);
 		
 		@JsonIgnore
-		@Property("port_sate")
+		@Property("port_state")
 		public Integer getPortState();
 		
 		@Property("port_state")
@@ -89,8 +90,7 @@
 		@JsonIgnore
 		@Incidence(label="on",direction = Direction.IN)
 		public ISwitchObject getSwitch();
-		
-		
+				
 		@JsonProperty("devices")
 		@Adjacency(label="host")
 		public Iterable<IDeviceObject> getDevices();
@@ -109,6 +109,16 @@
 		@Incidence(label="outport",direction = Direction.IN)
 		public Iterable<IFlowEntry> getOutFlowEntries();
 		
+		@JsonIgnore
+		@Adjacency(label="link")
+		public Iterable<IPortObject> getLinkedPorts();
+		
+		@Adjacency(label="link")
+		public void removeLink(final IPortObject dest_port);
+		
+		@Adjacency(label="link")
+		public void setLinkPort(final IPortObject dest_port);			
+		
 //		@JsonIgnore
 //		@Adjacency(label="link")
 //		public Iterable<ILinkObject> getLinks();
@@ -255,7 +265,7 @@
 		
 		@JsonIgnore
 		@GremlinGroovy("_().in('flow').out('switch')")
-		public Iterable<IDeviceObject> getSwitches();
+		public Iterable<ISwitchObject> getSwitches();
 		
 		@JsonIgnore
 		@Property("state")
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 1a9a9c5..0d49c03 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -2215,9 +2215,11 @@
         this.roleChanger = new RoleChanger();
         
 		String conf = configParams.get("dbconf");
-		if (conf == null) {
+		if (conf == null || conf.isEmpty()) {
 			conf = "/tmp/cassandra.titan";
+			log.debug("did not get DB config setting using default {}", conf);
 		}
+		log.debug("setting DB config {}", conf);
 		this.swStore = new SwitchStorageImpl();
 		this.swStore.init(conf);
 		
diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
index a068586..f040881 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
@@ -6,6 +6,7 @@
 import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
 import net.floodlightcontroller.core.ISwitchStorage;
 import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.util.GraphDBConnection.GenerateEvent;
 import net.onrc.onos.util.GraphDBConnection.Transaction;
 
 import org.openflow.protocol.OFPhysicalPort;
@@ -15,7 +16,7 @@
 import org.slf4j.LoggerFactory;
 
 public class SwitchStorageImpl implements ISwitchStorage {
-	public GraphDBConnection conn;
+	protected GraphDBConnection conn;
 	protected static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
 
 	@Override
@@ -182,6 +183,7 @@
             }
 		} catch (Exception e) {
              // TODO: handle exceptions
+			e.printStackTrace();
 			conn.endTx(Transaction.ROLLBACK);
 			log.info("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
 		}	
diff --git a/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java b/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
index b3c31ec..9f63fd7 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
@@ -28,21 +28,21 @@
 	@Override
 	public Iterable<ISwitchObject> getActiveSwitches() {
 		// TODO Auto-generated method stub
-		conn = GraphDBConnection.getInstance("");
+		conn = GraphDBConnection.getInstance("/tmp/cassandra.titan");
 		return conn.utils().getActiveSwitches(conn);
 	}
 
 	@Override
 	public Iterable<ISwitchObject> getAllSwitches() {
 		// TODO Auto-generated method stub
-		conn = GraphDBConnection.getInstance("");
+		conn = GraphDBConnection.getInstance("/tmp/cassandra.titan");
 		return conn.utils().getAllSwitches(conn);
 	}
 
 	@Override
 	public Iterable<ISwitchObject> getInactiveSwitches() {
 		// TODO Auto-generated method stub
-		conn = GraphDBConnection.getInstance("");
+		conn = GraphDBConnection.getInstance("/tmp/cassandra.titan");
 		return conn.utils().getInactiveSwitches(conn);
 	}
 
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
index 176a1a0..0ab52e2 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
@@ -5,12 +5,16 @@
 import java.util.List;
 import java.util.Set;
 
+import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
 import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
 import net.floodlightcontroller.core.INetMapTopologyService.ITopoSwitchService;
 import net.floodlightcontroller.core.internal.TopoSwitchServiceImpl;
 import net.floodlightcontroller.linkdiscovery.ILinkStorage;
 import net.floodlightcontroller.linkdiscovery.LinkInfo;
 import net.floodlightcontroller.routing.Link;
+import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.util.GraphDBConnection.GenerateEvent;
+import net.onrc.onos.util.GraphDBConnection.Transaction;
 
 import org.openflow.util.HexString;
 import org.slf4j.Logger;
@@ -23,6 +27,8 @@
 import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
 import com.tinkerpop.blueprints.Vertex;
 import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.util.wrappers.event.EventGraph;
+import com.tinkerpop.blueprints.util.wrappers.event.EventTransactionalGraph;
 import com.tinkerpop.gremlin.java.GremlinPipeline;
 import com.tinkerpop.pipes.PipeFunction;
 import com.tinkerpop.pipes.transform.PathPipe;
@@ -30,6 +36,7 @@
 public class LinkStorageImpl implements ILinkStorage {
 	public TitanGraph graph;
 	protected static Logger log = LoggerFactory.getLogger(LinkStorageImpl.class);
+	protected String conf;
 
 	@Override
 	public void update(Link link, DM_OPERATION op) {
@@ -70,7 +77,8 @@
 	}
 	
 	public void addOrUpdateLink(Link lt, LinkInfo linkinfo, DM_OPERATION op) {
-		Vertex vportSrc = null, vportDst = null;
+		GraphDBConnection conn = GraphDBConnection.getInstance(this.conf);
+		IPortObject vportSrc = null, vportDst = null;
 	
 		log.trace("addOrUpdateLink(): op {} {} {}", new Object[]{op, lt, linkinfo});
 		
@@ -78,18 +86,20 @@
             // get source port vertex
         	String dpid = HexString.toHexString(lt.getSrc());
         	short port = lt.getSrcPort();
-        	vportSrc = getPortVertex(dpid, port);
+        	vportSrc = conn.utils().searchPort(conn, dpid, port);
             
             // get dest port vertex
             dpid = HexString.toHexString(lt.getDst());
             port = lt.getDstPort();
-            vportDst = getPortVertex(dpid, port);
+            vportDst = conn.utils().searchPort(conn, dpid, port);
                         
             if (vportSrc != null && vportDst != null) {
-            	
+         	       	
             	// check if the link exists
-            	List<Vertex> currLinks = new ArrayList<Vertex>();
-            	for (Vertex V : vportSrc.query().direction(Direction.OUT).labels("link").vertices()) {
+            	List<IPortObject> currLinks = new ArrayList<IPortObject>();
+            	Iterable<IPortObject> currPorts = vportSrc.getLinkedPorts();
+            	
+            	for (IPortObject V : currPorts) {
             		currLinks.add(V);
             	}
             	
@@ -100,13 +110,13 @@
             					new Object[]{op, lt, vportSrc, vportDst});
             		}
             	} else {
-            		graph.addEdge(null, vportSrc, vportDst, "link");
-            		graph.stopTransaction(Conclusion.SUCCESS);
+            		conn.getFramedGraph().addEdge(null, vportSrc.asVertex(), vportDst.asVertex(), "link");
+            		conn.endTx(Transaction.COMMIT);
             		log.debug("addOrUpdateLink(): link added {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
             	}
             } else {
             	log.error("addOrUpdateLink(): failed invalid vertices {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
-            	graph.stopTransaction(Conclusion.FAILURE);
+            	conn.endTx(Transaction.ROLLBACK);
             }
         } catch (TitanException e) {
             /*
@@ -128,7 +138,8 @@
 
 	@Override
 	public void deleteLink(Link lt) {
-		Vertex vportSrc = null, vportDst = null;
+		GraphDBConnection conn = GraphDBConnection.getInstance(this.conf);
+		IPortObject vportSrc = null, vportDst = null;
 		int count = 0;
 		
 		log.debug("deleteLink(): {}", lt);
@@ -137,29 +148,33 @@
             // get source port vertex
          	String dpid = HexString.toHexString(lt.getSrc());
          	short port = lt.getSrcPort();
-         	vportSrc = getPortVertex(dpid, port);
+         	vportSrc = conn.utils().searchPort(conn, dpid, port);
             
             // get dst port vertex
          	dpid = HexString.toHexString(lt.getDst());
          	port = lt.getDstPort();
-         	vportDst = getPortVertex(dpid, port);
+         	vportDst = conn.utils().searchPort(conn, dpid, port);
+     		// FIXME: This needs to remove all edges
+         	// FIXME: Events will only be generated on singleton graph object (GraphDBConnection)
          	
          	if (vportSrc != null && vportDst != null) {
-         		for (Edge e : vportSrc.getEdges(Direction.OUT)) {
+
+   /*      		for (Edge e : vportSrc.asVertex().getEdges(Direction.OUT)) {
          			log.debug("deleteLink(): {} in {} out {}", 
          					new Object[]{e.getLabel(), e.getVertex(Direction.IN), e.getVertex(Direction.OUT)});
          			if (e.getLabel().equals("link") && e.getVertex(Direction.IN).equals(vportDst)) {
          				graph.removeEdge(e);
          				count++;
          			}
-         		}
-        		graph.stopTransaction(Conclusion.SUCCESS);
-            	log.debug("deleteLink(): deleted {} edges {} src {} dst {}", new Object[]{
-            			count, lt, vportSrc, vportDst});
+         		}*/
+         		vportSrc.removeLink(vportDst);
+        		conn.endTx(Transaction.COMMIT);
+            	log.debug("deleteLink(): deleted edges src {} dst {}", new Object[]{
+            			lt, vportSrc, vportDst});
             	
             } else {
             	log.error("deleteLink(): failed invalid vertices {} src {} dst {}", new Object[]{lt, vportSrc, vportDst});
-            	graph.stopTransaction(Conclusion.FAILURE);
+            	conn.endTx(Transaction.ROLLBACK);
             }
          	
         } catch (TitanException e) {
@@ -193,7 +208,8 @@
 	public void init(String conf) {
 		//TODO extract the DB location from properties
 	
-        graph = TitanFactory.open(conf);
+		this.conf = conf;
+        graph = TitanFactory.open(this.conf);
         
         // FIXME: These keys are not needed for Links but we better create it before using it as per titan
         Set<String> s = graph.getIndexedKeys(Vertex.class);
diff --git a/src/main/java/net/floodlightcontroller/onoslistener/OnosPublisher.java b/src/main/java/net/floodlightcontroller/onoslistener/OnosPublisher.java
index 585fc36..6d8087b 100644
--- a/src/main/java/net/floodlightcontroller/onoslistener/OnosPublisher.java
+++ b/src/main/java/net/floodlightcontroller/onoslistener/OnosPublisher.java
@@ -34,6 +34,8 @@
 import net.onrc.onos.registry.controller.IControllerRegistryService;
 import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
 import net.onrc.onos.registry.controller.RegistryException;
+import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.util.LocalTopologyEventListener;
 
 public class OnosPublisher implements IDeviceListener, IOFSwitchListener,
 		ILinkDiscoveryListener, IFloodlightModule {
@@ -43,6 +45,7 @@
 	protected static Logger log;
 	protected IDeviceService deviceService;
 	protected IControllerRegistryService registryService;
+	protected GraphDBConnection conn;
 	
 	protected static final String DBConfigFile = "dbconf";
 	protected static final String CleanupEnabled = "EnableCleanup";
@@ -198,6 +201,7 @@
 		// TODO Auto-generated method stub
 		Map<String, String> configMap = context.getConfigParams(this);
 		String conf = configMap.get(DBConfigFile);
+		conn = GraphDBConnection.getInstance(conf);
 		
 		log = LoggerFactory.getLogger(OnosPublisher.class);
 		deviceService = context.getServiceImpl(IDeviceService.class);
@@ -221,6 +225,9 @@
 		String cleanupNeeded = configMap.get(CleanupEnabled);
 
 		deviceService.addListener(this);
+		
+		log.debug("Adding EventListener");
+		conn.addEventListener(new LocalTopologyEventListener(conn));
 	       // Setup the Cleanup task. 
 		if (cleanupNeeded == null || !cleanupNeeded.equals("False")) {
 				ScheduledExecutorService ses = threadPool.getScheduledExecutor();
diff --git a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
index 7cf1cab..b8b3303 100644
--- a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
+++ b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
@@ -1,17 +1,43 @@
 package net.onrc.onos.flow;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Vertex;
 
 import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
 import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.util.DataPath;
+import net.floodlightcontroller.util.Dpid;
 import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.FlowEntryAction;
+import net.floodlightcontroller.util.FlowEntryMatch;
 import net.floodlightcontroller.util.FlowPath;
+import net.floodlightcontroller.util.Port;
+import net.floodlightcontroller.util.SwitchPort;
+import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.util.LocalTopologyEventListener;
+import net.onrc.onos.util.GraphDBConnection.Transaction;
 
 public class FlowManagerImpl implements IFlowManager {
+	
+	protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
+	protected static GraphDBConnection conn;
 
 	@Override
 	public void createFlow(IPortObject src_port, IPortObject dest_port) {
@@ -44,6 +70,7 @@
 	public void reconcileFlows(IPortObject src_port) {
 		// TODO Auto-generated method stub
 
+		log.debug("Reconcile Flows for Port removed: {}:{}",src_port.getSwitch().getDPID(),src_port.getNumber());
 		Iterable<IFlowEntry> flowEntries = src_port.getOutFlowEntries();
 
 		for(IFlowEntry fe: flowEntries) {
@@ -54,6 +81,29 @@
 
 	private void reconcileFlow(IFlowPath flow) {
 		// TODO Auto-generated method stub
+		String src_dpid = flow.getSrcSwitch();
+		String dst_dpid = flow.getDstSwitch();
+		Short src_port = flow.getSrcPort();
+		Short dst_port = flow.getDstPort();
+		IPortObject src = null;
+		IPortObject dst = null;
+		src = conn.utils().searchPort(conn, src_dpid, src_port);
+		dst = conn.utils().searchPort(conn, dst_dpid, dst_port);
+		if (src != null && dst != null) {
+			FlowPath newFlow = this.computeFlowPath(src,dst);
+			installFlow(newFlow);
+			removeFlow(flow);
+		}
+		
+	}
+
+	private void removeFlow(IFlowPath flow) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	private void installFlow(FlowPath newFlow) {
+		// TODO Auto-generated method stub
 		
 	}
 
@@ -66,7 +116,188 @@
 	@Override
 	public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
 		// TODO Auto-generated method stub
-		return null;
+		DataPath dataPath = new DataPath(); 
+		
+		// FIXME: Bad idea to use FloodLight data structures (SwitchPort)
+		
+		dataPath.setSrcPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
+						new Port(src_port.getNumber())));
+		dataPath.setDstPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
+				new Port(src_port.getNumber())));
+		
+		if (src_port.getSwitch().equals(dest_port.getSwitch())) {
+			// on same switch create quick path
+			FlowEntry flowEntry = new FlowEntry();
+		    flowEntry.setDpid(new Dpid(src_port.getSwitch().getDPID()));
+		    flowEntry.setInPort(new Port(src_port.getNumber()));
+		    flowEntry.setOutPort(new Port(src_port.getNumber()));
+		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
+		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
+		    
+		    // Set the outgoing port output action
+		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
+		    if (flowEntryActions == null) {
+			flowEntryActions = new ArrayList<FlowEntryAction>();
+			flowEntry.setFlowEntryActions(flowEntryActions);
+		    }
+		    FlowEntryAction flowEntryAction = new FlowEntryAction();
+		    flowEntryAction.setActionOutput(flowEntry.outPort());
+		    flowEntryActions.add(flowEntryAction);
+		    dataPath.flowEntries().add(flowEntry);
+		    
+		    FlowPath flowPath = new FlowPath();
+			flowPath.setDataPath(dataPath);
+
+			return flowPath;
+		}
+		Vertex v_src = src_port.getSwitch().asVertex();	
+		Vertex v_dest = dest_port.getSwitch().asVertex();
+
+		//
+		// Implement the Shortest Path computation by using Breath First Search
+		//
+		Set<Vertex> visitedSet = new HashSet<Vertex>();
+		Queue<Vertex> processingList = new LinkedList<Vertex>();
+		Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
+
+		processingList.add(v_src);
+		visitedSet.add(v_src);
+		Boolean path_found = false;
+		while (! processingList.isEmpty()) {
+		    Vertex nextVertex = processingList.poll();
+		    if (v_dest.equals(nextVertex)) {
+			path_found = true;
+			break;
+		    }
+		    for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
+			for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
+			    for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
+				// Ignore inactive switches
+				String state = child.getProperty("state").toString();
+				if (! state.equals(SwitchState.ACTIVE.toString()))
+				    continue;
+
+				if (! visitedSet.contains(child)) {
+				    previousVertexMap.put(parentPort, nextVertex);
+				    previousVertexMap.put(childPort, parentPort);
+				    previousVertexMap.put(child, childPort);
+				    visitedSet.add(child);
+				    processingList.add(child);
+				}
+			    }
+			}
+		    }
+		}
+		if (! path_found) {
+		    return null;		// No path found
+		}
+
+		List<Vertex> resultPath = new LinkedList<Vertex>();
+		Vertex previousVertex = v_dest;
+		resultPath.add(v_dest);
+		while (! v_src.equals(previousVertex)) {
+		    Vertex currentVertex = previousVertexMap.get(previousVertex);
+		    resultPath.add(currentVertex);
+		    previousVertex = currentVertex;
+		}
+		Collections.reverse(resultPath);
+		
+		// Loop through the result and prepare the return result
+		// as a list of Flow Entries.
+		//
+		long nodeId = 0;
+		short portId = 0;
+		Port inPort = new Port(src_port.getNumber());
+		Port outPort = new Port();
+		int idx = 0;
+		for (Vertex v: resultPath) {
+		    String type = v.getProperty("type").toString();
+		    // System.out.println("type: " + type);
+		    if (type.equals("port")) {
+			String number = v.getProperty("number").toString();
+			// System.out.println("number: " + number);
+
+			Object obj = v.getProperty("number");
+			// String class_str = obj.getClass().toString();
+			if (obj instanceof Short) {
+			    portId = (Short)obj;
+			} else if (obj instanceof Integer) {
+			    Integer int_nodeId = (Integer)obj;
+			    portId = int_nodeId.shortValue();
+			    // int int_nodeId = (Integer)obj;
+			    // portId = (short)int_nodeId.;
+			}
+		    } else if (type.equals("switch")) {
+			String dpid = v.getProperty("dpid").toString();
+			nodeId = HexString.toLong(dpid);
+
+			// System.out.println("dpid: " + dpid);
+		    }
+		    idx++;
+		    if (idx == 1) {
+			continue;
+		    }
+		    int mod = idx % 3;
+		    if (mod == 0) {
+			// Setup the incoming port
+			inPort = new Port(portId);
+			continue;
+		    }
+		    if (mod == 2) {
+			// Setup the outgoing port, and add the Flow Entry
+			outPort = new Port(portId);
+
+			FlowEntry flowEntry = new FlowEntry();
+			flowEntry.setDpid(new Dpid(nodeId));
+			flowEntry.setInPort(inPort);
+			flowEntry.setOutPort(outPort);
+			flowEntry.setFlowEntryMatch(new FlowEntryMatch());
+		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
+		    
+		    // Set the outgoing port output action
+		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
+		    if (flowEntryActions == null) {
+			flowEntryActions = new ArrayList<FlowEntryAction>();
+			flowEntry.setFlowEntryActions(flowEntryActions);
+		    }
+		    FlowEntryAction flowEntryAction = new FlowEntryAction();
+		    flowEntryAction.setActionOutput(flowEntry.outPort());
+		    flowEntryActions.add(flowEntryAction);
+		    dataPath.flowEntries().add(flowEntry);
+			continue;
+		    }
+		}
+		if (idx > 0) {
+		    // Add the last Flow Entry
+		    FlowEntry flowEntry = new FlowEntry();
+		    flowEntry.setDpid(new Dpid(nodeId));
+		    flowEntry.setInPort(inPort);
+		    flowEntry.setOutPort(new Port(dest_port.getNumber()));
+		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
+		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
+		    
+		    // Set the outgoing port output action
+		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
+		    if (flowEntryActions == null) {
+			flowEntryActions = new ArrayList<FlowEntryAction>();
+			flowEntry.setFlowEntryActions(flowEntryActions);
+		    }
+		    FlowEntryAction flowEntryAction = new FlowEntryAction();
+		    flowEntryAction.setActionOutput(flowEntry.outPort());
+		    flowEntryActions.add(flowEntryAction);
+		    dataPath.flowEntries().add(flowEntry);
+		    dataPath.flowEntries().add(flowEntry);
+		}
+
+	
+		if (dataPath.flowEntries().size() > 0) {
+		    FlowPath flowPath = new FlowPath();
+			flowPath.setDataPath(dataPath);
+
+			return flowPath;
+		}
+		return null;		
+		
 	}
 
 	@Override
@@ -106,5 +337,6 @@
 		// TODO Auto-generated method stub
 		return false;
 	}
+	
 
 }
diff --git a/src/main/java/net/onrc/onos/util/GraphDBConnection.java b/src/main/java/net/onrc/onos/util/GraphDBConnection.java
index ee50cd0..84a0501 100644
--- a/src/main/java/net/onrc/onos/util/GraphDBConnection.java
+++ b/src/main/java/net/onrc/onos/util/GraphDBConnection.java
@@ -2,10 +2,15 @@
 
 import java.util.Set;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.thinkaurelius.titan.core.TitanFactory;
 import com.thinkaurelius.titan.core.TitanGraph;
-import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.TransactionalGraph;
 import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.wrappers.event.EventTransactionalGraph;
 import com.tinkerpop.frames.FramedGraph;
 
 public class GraphDBConnection {
@@ -13,9 +18,23 @@
 		COMMIT,
 		ROLLBACK
 	}
+	public enum GenerateEvent {
+		TRUE,
+		FALSE
+	}
+	class TransactionHandle {
+		protected TransactionalGraph tr;
+		public void create() {
+			tr = graph.startTransaction();			
+		}
+	}
+	protected static Logger log = LoggerFactory.getLogger(GraphDBConnection.class);
 	private static GraphDBConnection singleton = new GraphDBConnection( );
 	private static TitanGraph graph;
+	private static EventTransactionalGraph<TitanGraph> eg;
 	private static GraphDBUtils utils;
+	private static String configFile;
+
 	   
 	   /* A private Constructor prevents any other 
 	    * class from instantiating.
@@ -23,9 +42,14 @@
 	   private GraphDBConnection(){ }
 	   
 	   /* Static 'instance' method */
-	   public static GraphDBConnection getInstance(String conf) {
-		   if (graph == null||graph.isOpen() == Boolean.FALSE) {
-		        graph = TitanFactory.open(conf);		        
+	   public static GraphDBConnection getInstance(final String conf) {
+		   if (GraphDBConnection.configFile == null || GraphDBConnection.configFile.isEmpty()) {
+			   GraphDBConnection.configFile = conf;
+			   log.debug("GraphDBConnection::Setting Config File {}", GraphDBConnection.configFile);
+		   }
+		   if (!GraphDBConnection.configFile.isEmpty() && 
+				   (graph == null||graph.isOpen() == Boolean.FALSE)) {
+		        graph = TitanFactory.open(GraphDBConnection.configFile);		        
 		        // FIXME: Creation on Indexes should be done only once
 		        Set<String> s = graph.getIndexedKeys(Vertex.class);
 		        if (!s.contains("dpid")) {
@@ -44,8 +68,9 @@
 		        	graph.createKeyIndex("flow_entry_id",
 						     Vertex.class);
 		        }
-		   }
-		   graph.stopTransaction(Conclusion.SUCCESS);
+		        graph.stopTransaction(Conclusion.SUCCESS);
+		        eg = new EventTransactionalGraph<TitanGraph>(graph);
+		   }		   
 		   if (utils == null) {
 			   utils = new GraphDBUtils();
 		   }
@@ -56,7 +81,7 @@
 		   return utils;
 	   }
 	   
-	   protected FramedGraph<TitanGraph> getFramedGraph() {
+	   public FramedGraph<TitanGraph> getFramedGraph() {
 	   
 		   	if (isValid()) {
 		   		FramedGraph<TitanGraph> fg = new FramedGraph<TitanGraph>(graph);
@@ -66,6 +91,21 @@
 		   	}
 	   }
 	   
+	   protected EventTransactionalGraph<TitanGraph> getEventGraph() {
+		   
+		   	if (isValid()) {		   		
+		   		return eg;
+		   	} else {
+		   		return null;
+		   	}
+	   }
+	   
+	   public void addEventListener(final LocalGraphChangedListener listener) {		   
+		   EventTransactionalGraph<TitanGraph> eg = this.getEventGraph();
+		   eg.addListener(listener);
+		   log.debug("Registered listener {}",listener.getClass());
+	   }
+	   
 	   public Boolean isValid() {
 		   
 		   return (graph != null||graph.isOpen());
@@ -73,19 +113,61 @@
 	   
 	   public void startTx() {
 		   
+		   
 	   }
 	   
 	   public void endTx(Transaction tx) {
+		   try {
+			switch (tx) {
+			   case COMMIT:
+				   graph.stopTransaction(Conclusion.SUCCESS);
+			   case ROLLBACK:
+				   graph.stopTransaction(Conclusion.FAILURE);
+			   }
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	   }
+	   
+	   public void endTx(TransactionHandle tr, Transaction tx) {
 		   switch (tx) {
 		   case COMMIT:
-			   graph.stopTransaction(Conclusion.SUCCESS);
+			   if (tr != null && tr.tr != null) {
+				   tr.tr.stopTransaction(Conclusion.SUCCESS);
+			   } else {
+				   graph.stopTransaction(Conclusion.SUCCESS);
+			   }
 		   case ROLLBACK:
-			   graph.stopTransaction(Conclusion.FAILURE);
+			   if (tr != null && tr.tr != null) {
+				   tr.tr.stopTransaction(Conclusion.FAILURE);
+			   } else {
+				   graph.stopTransaction(Conclusion.FAILURE);
+			   }
 		   }
+	   }   
+	   
+	   public void endTx(Transaction tx, GenerateEvent fire) {
+
+		   try {
+			if (fire.equals(GenerateEvent.TRUE)) {
+				   switch (tx) {
+				   case COMMIT:
+					   eg.stopTransaction(Conclusion.SUCCESS);
+				   case ROLLBACK:
+					   eg.stopTransaction(Conclusion.FAILURE);
+				   }
+			   } else {
+					endTx(tx);   			   
+			   }
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
 	   }
 	   
 	   public void close() {
-		   graph.stopTransaction(Conclusion.SUCCESS);
+//		   graph.shutdown();
 	   }
 	   
 }
diff --git a/src/main/java/net/onrc/onos/util/GraphDBUtils.java b/src/main/java/net/onrc/onos/util/GraphDBUtils.java
index 1646fc7..eea57fd 100644
--- a/src/main/java/net/onrc/onos/util/GraphDBUtils.java
+++ b/src/main/java/net/onrc/onos/util/GraphDBUtils.java
@@ -3,12 +3,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import com.thinkaurelius.titan.core.TitanGraph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.frames.FramedGraph;
-import com.tinkerpop.frames.FramedVertexIterable;
-import com.tinkerpop.gremlin.java.GremlinPipeline;
-
 import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
@@ -18,6 +12,12 @@
 import net.floodlightcontroller.util.FlowEntryId;
 import net.floodlightcontroller.util.FlowId;
 
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.frames.FramedGraph;
+import com.tinkerpop.frames.FramedVertexIterable;
+import com.tinkerpop.gremlin.java.GremlinPipeline;
+
 public class GraphDBUtils implements IDBUtils {
 	
 	@Override
@@ -44,16 +44,6 @@
 	}
 
 	@Override
-	public ISwitchObject searchActiveSwitch(GraphDBConnection conn, String dpid) {
-	    ISwitchObject sw = searchSwitch(conn, dpid);
-	    if ((sw != null) &&
-		sw.getState().equals(SwitchState.ACTIVE.toString())) {
-		return sw;
-	    }
-	    return null;
-	}
-
-	@Override
 	public IDeviceObject searchDevice(GraphDBConnection conn, String macAddr) {
 		// TODO Auto-generated method stub
 		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
@@ -65,11 +55,24 @@
 	@Override
 	public IPortObject searchPort(GraphDBConnection conn, String dpid, short number) {
 		ISwitchObject sw = searchSwitch(conn, dpid);
+//		if (sw != null) {
+//			
+//			IPortObject port = null;
+//			try {
+//				port = sw.getPort(number);
+//			} catch (Exception e) {
+//				// TODO Auto-generated catch block
+//				e.printStackTrace();
+//			}
+//			
+//			return port;
+//		}
+//		return null;
 		GremlinPipeline<Vertex, IPortObject> pipe = new GremlinPipeline<Vertex, IPortObject>();
 		pipe.start(sw.asVertex());
 	    pipe.out("on").has("number", number);
-	    FramedVertexIterable<IPortObject> r = new FramedVertexIterable(conn.getFramedGraph(), pipe, IPortObject.class);
-	    return r.iterator().hasNext() ? r.iterator().next() : null;		
+	    FramedVertexIterable<IPortObject> r = new FramedVertexIterable<IPortObject>(conn.getFramedGraph(), (Iterable) pipe, IPortObject.class);
+	    return r.iterator().hasNext() ? r.iterator().next() : null;
 	}
 
 	@Override
@@ -89,6 +92,7 @@
 	@Override
 	public void removePort(GraphDBConnection conn, IPortObject port) {
 		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+//		EventGraph<TitanGraph> eg = conn.getEventGraph();
 		fg.removeVertex(port.asVertex());		
 	}
 
@@ -135,7 +139,7 @@
 		GremlinPipeline<Vertex, IFlowPath> pipe = new GremlinPipeline<Vertex, IFlowPath>();
 		pipe.start(flowEntry.asVertex());
 		pipe.out("flow");
-		FramedVertexIterable<IFlowPath> r = new FramedVertexIterable(conn.getFramedGraph(), pipe, IFlowPath.class);
+		FramedVertexIterable<IFlowPath> r = new FramedVertexIterable(conn.getFramedGraph(), (Iterable) pipe, IFlowPath.class);
 		return r.iterator().hasNext() ? r.iterator().next() : null;
 	}
 
@@ -219,4 +223,10 @@
 		}
 		return inactiveSwitches;
 	}
+
+	@Override
+	public ISwitchObject searchActiveSwitch(GraphDBConnection conn, String dpid) {
+		// TODO Auto-generated method stub
+		return null;
+	}
 }
diff --git a/src/main/java/net/onrc/onos/util/LocalGraphChangedListener.java b/src/main/java/net/onrc/onos/util/LocalGraphChangedListener.java
new file mode 100644
index 0000000..ac819f9
--- /dev/null
+++ b/src/main/java/net/onrc/onos/util/LocalGraphChangedListener.java
@@ -0,0 +1,7 @@
+package net.onrc.onos.util;
+
+import com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener;
+
+public interface LocalGraphChangedListener extends GraphChangedListener {
+
+}
diff --git a/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java b/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
index 186ba58..17d4b2a 100644
--- a/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
+++ b/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
@@ -1,10 +1,6 @@
 package net.onrc.onos.util;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.linkdiscovery.internal.TopoLinkServiceImpl;
-import net.floodlightcontroller.util.FlowPath;
 import net.onrc.onos.flow.FlowManagerImpl;
 import net.onrc.onos.flow.IFlowManager;
 
@@ -15,12 +11,15 @@
 import com.tinkerpop.blueprints.Direction;
 import com.tinkerpop.blueprints.Edge;
 import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener;
 
-public class LocalTopologyEventListener implements GraphChangedListener {
+public class LocalTopologyEventListener implements LocalGraphChangedListener {
 	
 	protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
-	protected static GraphDBConnection conn = GraphDBConnection.getInstance("");
+	protected static GraphDBConnection conn;
+	
+	public LocalTopologyEventListener(GraphDBConnection conn) {
+		LocalTopologyEventListener.conn = conn;		
+	}
 
 	@Override
 	public void edgeAdded(Edge arg0) {
@@ -28,11 +27,6 @@
 		// Convert this Event into NetMapEvent (LinkAdded, FlowEntryEnabled, HostAttached, PortEnabled)
 	}
 
-	@Override
-	public void edgePropertyChanged(Edge arg0, String arg1, Object arg2) {
-		// TODO Auto-generated method stub
-        // Generate State change events on edges too
-	}
 
 	@Override
 	public void edgePropertyRemoved(Edge arg0, String arg1, Object arg2) {
@@ -71,22 +65,38 @@
 	}
 
 	@Override
-	public void vertexPropertyChanged(Vertex arg0, String arg1, Object arg2) {
-		// TODO Auto-generated method stub
-		
-
-	}
-
-	@Override
 	public void vertexPropertyRemoved(Vertex arg0, String arg1, Object arg2) {
 		// TODO Auto-generated method stub
 
 	}
 
 	@Override
-	public void vertexRemoved(Vertex arg0) {
+	public void vertexRemoved(Vertex vertex) {
 		// TODO Auto-generated method stub
+		// Generate NetMapEvents 
+		String type = (String) vertex.getProperty("type");
+		log.debug("TopologyEvents: Received vertex removed event: {}",vertex.toString());
+		if (type.equals("port")) {
+			// port is removed...lets fire reconcile here directly for now
+			
+			IPortObject src_port = conn.getFramedGraph().frame(vertex, IPortObject.class);
+			log.debug("TopologyEvents: Port removed: {}:{}",src_port.getSwitch().getDPID(),src_port.getNumber());
+			IFlowManager manager = new FlowManagerImpl();
+			manager.reconcileFlows(src_port);			
+		}
+	}
 
+
+	@Override
+	public void edgePropertyChanged(Edge arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void vertexPropertyChanged(Vertex arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+		
 	}
 
 }
diff --git a/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java b/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
index cea67c3..3d5e03b 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
@@ -27,7 +27,8 @@
 	
 	public static TitanGraph getTestDatabase(){
 		//return TitanFactory.open(testDbLocation);
-		return TitanFactory.openInMemoryGraph();
+//		return TitanFactory.openInMemoryGraph();
+		return TitanFactory.open(testDbLocation);
 	}
 	
 	public static void populateTestData(TitanGraph titanGraph){
diff --git a/start-onos.sh b/start-onos.sh
index 1263b8a..7e23eaf 100755
--- a/start-onos.sh
+++ b/start-onos.sh
@@ -91,7 +91,7 @@
 
 function stop {
   # Kill the existing processes
-  flpid=`ps -edalf |grep java |grep logback.xml | awk '{print $4}'`
+  flpid=`jps -l |grep ${MAIN_CLASS} | awk '{print $1}'`
   tdpid=`ps -edalf |grep tcpdump |grep ${PCAP_LOG} | awk '{print $4}'`
   pids="$flpid $tdpid"
   for p in ${pids}; do
diff --git a/test-network/mininet/mrun b/test-network/mininet/mrun
new file mode 100755
index 0000000..8bcd141
--- /dev/null
+++ b/test-network/mininet/mrun
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Attach to a Mininet host and run a command
+
+if [ -z $1 ]; then
+  echo "usage: $0 host cmd [args...]"
+  exit 1
+else
+  host=$1
+fi
+
+pid=`pgrep -f ${host}.banner`
+if [ "$pid" == "" ]; then
+  echo "Could not find Mininet host $host"
+  exit 2
+fi
+
+if [ -z $2 ]; then
+  cmd='bash'
+else
+  shift
+  cmd=$*
+fi
+
+cgroup=/sys/fs/cgroup/cpu/$host
+if [ -d "$cgroup" ]; then
+  cg="-g $host"
+fi
+
+exec sudo mnexec -a $pid $cg $cmd
diff --git a/web/pingallm.py b/web/pingallm.py
new file mode 100755
index 0000000..e377a55
--- /dev/null
+++ b/web/pingallm.py
@@ -0,0 +1,61 @@
+#! /usr/bin/env python
+import sys
+import time
+import os
+
+hosts=['onosdevz1', 'onosdevz2', 'onosdevz3', 'onosdevz4', 'onosdevz5', 'onosdevz6', 'onosdevz7', 'onosdevz8']
+filename = sys.argv[1]
+
+ping_cnt=3
+wait=ping_cnt
+
+os.popen("rm -f /tmp/ping*")
+
+f = open(filename, 'r')
+nr_ping = 0
+for line in f:
+  if line[0] != "#":
+    fid=int(line.strip().split()[0])
+    src_dpid=line.strip().split()[2]
+    dst_dpid=line.strip().split()[4]
+    src_nwid=int(src_dpid.split(':')[-2], 16)
+    dst_nwid=int(dst_dpid.split(':')[-2], 16)
+    src_hostid=int(src_dpid.split(':')[-1], 16)
+    dst_hostid=int(dst_dpid.split(':')[-1], 16)
+    cmd="echo \"192.168.%d.%d -> 192.168.%d.%d\" > /tmp/ping.%d" % (src_nwid, src_hostid, dst_nwid, dst_hostid,fid)
+    os.popen(cmd)
+    cmd="ssh %s \'${HOME}/ONOS/test-network/mininet/mrun host%d \'ping -c %d -W 1 192.168.%d.%d\'\' >> /tmp/ping.%d 2>&1 &" % (hosts[src_nwid-1], src_hostid, ping_cnt, dst_nwid, dst_hostid,fid)
+#    print cmd
+    result = os.popen(cmd).read()
+    time.sleep(0.2)
+    nr_ping = nr_ping + 1
+
+print "waiting for ping(s) to finish (%d sec)" % (wait)
+time.sleep(wait)
+cmd="cat /tmp/ping.* | grep loss |wc -l"
+wait_cnt=0
+while 1:
+  nr_done = int(os.popen(cmd).read())
+  if nr_done == nr_ping or wait_cnt > 10:
+    break
+  print "%d ping finished" % nr_done
+  time.sleep(1)
+  wait_cnt += 1
+
+cmd='cat /tmp/ping.* | grep " 0% packet loss" |wc -l'
+nr_success = int(os.popen(cmd).read())
+
+if nr_success != nr_ping:
+  print "fail: %d ping(s) failed (finished %d total %d)" % (nr_done - nr_success, nr_done, nr_ping)
+else:
+  print "success: all %d ping(s) got through" % (nr_success)
+
+for i in range(nr_ping):
+  cmd="cat /tmp/ping.%d | grep loss | awk '{print $6}'" % (i+1)
+  cmd2="cat /tmp/ping.%d | head -n 1" % (i+1)
+  result = os.popen(cmd).read().strip()
+  result2 = os.popen(cmd2).read().strip()
+  if result != "0%":
+    print "flow # %d fail (%s)" % (i+1, result2)
+
+f.close()
diff --git a/web/shortest_path.py b/web/shortest_path.py
index 0f23bf4..b379a82 100755
--- a/web/shortest_path.py
+++ b/web/shortest_path.py
@@ -20,7 +20,7 @@
 ControllerIP="127.0.0.1"
 ControllerPort=8080
 
-DEBUG=0
+DEBUG=1
 pp = pprint.PrettyPrinter(indent=4)
 
 app = Flask(__name__)