Merge upstream changes
diff --git a/cluster-mgmt/common/onos.properties b/cluster-mgmt/common/onos.properties
deleted file mode 100644
index 13fca75..0000000
--- a/cluster-mgmt/common/onos.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-floodlight.modules = net.floodlightcontroller.storage.memory.MemoryStorageSource,\
-net.floodlightcontroller.core.FloodlightProvider,\
-net.floodlightcontroller.threadpool.ThreadPool,\
-net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl,\
-net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher,\
-net.floodlightcontroller.firewall.Firewall,\
-net.floodlightcontroller.jython.JythonDebugInterface,\
-net.floodlightcontroller.counter.CounterStore,\
-net.floodlightcontroller.perfmon.PktInProcessingTime,\
-net.floodlightcontroller.ui.web.StaticWebRoutable,\
-net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher, \
-net.onrc.onos.registry.controller.ZookeeperRegistry
-net.floodlightcontroller.restserver.RestApiServer.port = 8080
-net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
-net.floodlightcontroller.jython.JythonDebugInterface.port = 6655
-net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
-net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
-net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = /tmp/cassandra.titan
diff --git a/cluster-mgmt/cp-config.sh b/cluster-mgmt/cp-config.sh
index e3b2108..e6db9d3 100755
--- a/cluster-mgmt/cp-config.sh
+++ b/cluster-mgmt/cp-config.sh
@@ -22,7 +22,7 @@
 #dsh -g $basename 'cd ONOS; ./stop-cassandra stop'
 #dsh -g $basename '$ZK_DIR/bin/zkServer.sh stop'
 
-# authorized_keys  cassandra.yaml  hosts  id_rsa  id_rsa.pub  known_hosts  onlab-gui.pem  onlabkey.pem  onos.properties  zoo.cfg
+# authorized_keys  cassandra.yaml  hosts  id_rsa  id_rsa.pub  known_hosts  onlab-gui.pem  onlabkey.pem  zoo.cfg
 ## SSH Setting
 dsh -g $basename 'mkdir -m 700 .ssh' 
 for n in $SSH_COPY; do
diff --git a/conf/onos-embedded.properties b/conf/onos-embedded.properties
index 8bbf25d..777ff2b 100644
--- a/conf/onos-embedded.properties
+++ b/conf/onos-embedded.properties
@@ -9,6 +9,7 @@
 net.floodlightcontroller.ui.web.StaticWebRoutable,\
 net.onrc.onos.datagrid.HazelcastDatagrid,\
 net.onrc.onos.ofcontroller.flowmanager.FlowManager,\
+net.onrc.onos.ofcontroller.topology.TopologyManager,\
 net.onrc.onos.registry.controller.ZookeeperRegistry
 net.floodlightcontroller.restserver.RestApiServer.port = 8080
 net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
diff --git a/conf/onos.properties b/conf/onos.properties
index c67b340..e858adb 100644
--- a/conf/onos.properties
+++ b/conf/onos.properties
@@ -9,6 +9,7 @@
 net.floodlightcontroller.ui.web.StaticWebRoutable,\
 net.onrc.onos.datagrid.HazelcastDatagrid,\
 net.onrc.onos.ofcontroller.flowmanager.FlowManager,\
+net.onrc.onos.ofcontroller.topology.TopologyManager,\
 net.onrc.onos.registry.controller.ZookeeperRegistry
 net.floodlightcontroller.restserver.RestApiServer.port = 8080
 net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
diff --git a/pom.xml b/pom.xml
index 41a9b14..002ba60 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,7 @@
             <exclude>**/*TestCase.java</exclude>
           -->
           </excludes>
+          <argLine>-XX:MaxPermSize=256m</argLine>
         </configuration>
       </plugin>
       <!-- exec:java -->
@@ -357,7 +358,7 @@
     <dependency>
       <groupId>org.easymock</groupId>
       <artifactId>easymock</artifactId>
-      <version>3.2</version>
+      <version>3.1</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 44510a7..134a3b0 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -2352,7 +2352,7 @@
                         // new controller node IP
                         addedControllerNodeIPs.put(controllerID, discoveredIP);
                     } 
-                    else if (curIP.equals(discoveredIP)) {
+                    else if (!curIP.equals(discoveredIP)) {
                         // IP changed                    
                         removedControllerNodeIPs.put(controllerID, curIP);
                         addedControllerNodeIPs.put(controllerID, discoveredIP);
diff --git a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
index 7736880..3ff773e 100644
--- a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
+++ b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
@@ -27,9 +27,7 @@
  * appropriate in a multi-node cluster.
  */
 public class HazelcastDatagrid implements IFloodlightModule, IDatagridService {
-    protected static Logger log =
-	LoggerFactory.getLogger(HazelcastDatagrid.class);
-
+    protected static Logger log = LoggerFactory.getLogger(HazelcastDatagrid.class);
     protected IFloodlightProviderService floodlightProvider;
 
     protected static final String HazelcastConfigFile = "datagridConfig";
@@ -101,7 +99,7 @@
     public Map<Class<? extends IFloodlightService>, IFloodlightService> 
 			       getServiceImpls() {
         Map<Class<? extends IFloodlightService>,
-        IFloodlightService> m = 
+	    IFloodlightService> m = 
             new HashMap<Class<? extends IFloodlightService>,
                 IFloodlightService>();
         m.put(IDatagridService.class, this);
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
index 2766ea8..79cca4b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -42,6 +42,7 @@
 import net.onrc.onos.ofcontroller.proxyarp.IProxyArpService;
 import net.onrc.onos.ofcontroller.proxyarp.ProxyArpManager;
 import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
+import net.onrc.onos.ofcontroller.topology.Topology;
 import net.onrc.onos.ofcontroller.topology.TopologyManager;
 import net.onrc.onos.ofcontroller.util.DataPath;
 import net.onrc.onos.ofcontroller.util.Dpid;
@@ -82,7 +83,7 @@
 	private static Logger log = LoggerFactory.getLogger(BgpRoute.class);
 
 	private IFloodlightProviderService floodlightProvider;
-	private ITopologyService topology;
+	private ITopologyService topologyService;
 	private ITopologyNetService topologyNetService;
 	private ILinkDiscoveryService linkDiscoveryService;
 	private IRestApiService restApi;
@@ -142,8 +143,8 @@
 	
 	private FlowCache flowCache;
 	
-	private volatile Map<Long, ?> shortestPathTopo = null;
-
+	private volatile Topology topology = null;
+		
 	private class TopologyChangeDetector implements Runnable {
 		@Override
 		public void run() {
@@ -260,13 +261,13 @@
 	    	
 		// Register floodlight provider and REST handler.
 		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-		topology = context.getServiceImpl(ITopologyService.class);
+		topologyService = context.getServiceImpl(ITopologyService.class);
 		linkDiscoveryService = context.getServiceImpl(ILinkDiscoveryService.class);
 		restApi = context.getServiceImpl(IRestApiService.class);
 		
 		//TODO We'll initialise this here for now, but it should really be done as
 		//part of the controller core
-		proxyArp = new ProxyArpManager(floodlightProvider, topology, this, restApi);
+		proxyArp = new ProxyArpManager(floodlightProvider, topologyService, this, restApi);
 		
 		linkUpdates = new ArrayList<LDUpdate>();
 		ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
@@ -318,7 +319,7 @@
 	@Override
 	public void startUp(FloodlightModuleContext context) {
 		restApi.addRestletRoutable(new BgpRouteWebRoutable());
-		topology.addListener(this);
+		topologyService.addListener(this);
 		floodlightProvider.addOFSwitchListener(this);
 		
 		proxyArp.startUp();
@@ -498,14 +499,14 @@
 		//Add a flow to rewrite mac for this prefix to all other border switches
 		for (Interface srcInterface : srcInterfaces.values()) {
 			DataPath shortestPath; 
-			if (shortestPathTopo == null) {
-				shortestPath = topologyNetService.getShortestPath(
+			if (topology == null) {
+				shortestPath = topologyNetService.getDatabaseShortestPath(
 						srcInterface.getSwitchPort(),
 						egressInterface.getSwitchPort());
 			}
 			else {
-				shortestPath = topologyNetService.getTopoShortestPath(
-						shortestPathTopo, srcInterface.getSwitchPort(),
+				shortestPath = topologyNetService.getTopologyShortestPath(
+						topology, srcInterface.getSwitchPort(),
 						egressInterface.getSwitchPort());
 			}
 			
@@ -697,12 +698,12 @@
 			}
 			
 			DataPath shortestPath;
-			if (shortestPathTopo == null) {
-				shortestPath = topologyNetService.getShortestPath(
+			if (topology == null) {
+				shortestPath = topologyNetService.getDatabaseShortestPath(
 						srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
 			}
 			else {
-				shortestPath = topologyNetService.getTopoShortestPath(shortestPathTopo, 
+				shortestPath = topologyNetService.getTopologyShortestPath(topology, 
 						srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
 			}
 			
@@ -771,7 +772,7 @@
 		for (BgpPeer bgpPeer : bgpPeers.values()){
 			Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
 			
-			DataPath path = topologyNetService.getShortestPath(
+			DataPath path = topologyNetService.getDatabaseShortestPath(
 					peerInterface.getSwitchPort(), bgpdAttachmentPoint);
 			
 			if (path == null){
@@ -1046,7 +1047,7 @@
 	
 	private void beginRouting(){
 		log.debug("Topology is now ready, beginning routing function");
-		shortestPathTopo = topologyNetService.prepareShortestPathTopo();
+		topology = topologyNetService.newDatabaseTopology();
 		
 		setupArpFlows();
 		setupDefaultDropFlows();
@@ -1086,7 +1087,7 @@
 					continue;
 				}
 				
-				DataPath shortestPath = topologyNetService.getShortestPath(
+				DataPath shortestPath = topologyNetService.getDatabaseShortestPath(
 						srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
 				
 				if (shortestPath == null){
@@ -1193,7 +1194,7 @@
 		}
 		
 		boolean refreshNeeded = false;
-		for (LDUpdate ldu : topology.getLastLinkUpdates()){
+		for (LDUpdate ldu : topologyService.getLastLinkUpdates()){
 			if (!ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_UPDATED)){
 				//We don't need to recalculate anything for just link updates
 				//They happen very frequently
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
index 978fcde..cd3cf15 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
@@ -18,7 +18,7 @@
 	}
 
 	public TopoSwitchServiceImpl() {
-		this("/tmp/cassandra.titan");
+		this("");
 	}
 	
 	public void finalize() {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/INetworkGraphService.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/INetworkGraphService.java
new file mode 100644
index 0000000..121eaf9
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/INetworkGraphService.java
@@ -0,0 +1,10 @@
+package net.onrc.onos.ofcontroller.floodlightlistener;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+/**
+ * Interface for providing Network Graph Service to other module.
+ */
+public interface INetworkGraphService extends IFloodlightService {
+    // TODO
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
index e0ac4e1..6db2009 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
@@ -2,6 +2,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -44,8 +45,12 @@
 import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
 import net.onrc.onos.registry.controller.RegistryException;
 
-public class NetworkGraphPublisher implements IDeviceListener, IOFSwitchListener, IOFSwitchPortListener,
-		ILinkDiscoveryListener, IFloodlightModule {
+public class NetworkGraphPublisher implements IDeviceListener,
+					      IOFSwitchListener,
+					      IOFSwitchPortListener,
+					      ILinkDiscoveryListener,
+					      IFloodlightModule,
+					      INetworkGraphService {
 	
 	protected IDeviceStorage devStore;
 	protected ISwitchStorage swStore;
@@ -226,14 +231,20 @@
 
 	@Override
 	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-		// TODO Auto-generated method stub
-		return null;
+		Collection<Class<? extends IFloodlightService>> l =
+		    new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(INetworkGraphService.class);
+		return l;
 	}
 
 	@Override
 	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
-		// TODO Auto-generated method stub
-		return null;
+		Map<Class<? extends IFloodlightService>,
+		    IFloodlightService> m =
+		    new HashMap<Class<? extends IFloodlightService>,
+		    IFloodlightService>();
+		m.put(INetworkGraphService.class, this);
+		return m;
 	}
 
 	@Override
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
index 2c5f4ba..82aa25c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -27,14 +27,18 @@
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.util.MACAddress;
 import net.floodlightcontroller.util.OFMessageDamper;
+
+import net.onrc.onos.datagrid.IDatagridService;
 import net.onrc.onos.graph.GraphDBOperation;
 import net.onrc.onos.ofcontroller.core.INetMapStorage;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
 import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
 import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
+import net.onrc.onos.ofcontroller.topology.Topology;
 import net.onrc.onos.ofcontroller.topology.TopologyManager;
 import net.onrc.onos.ofcontroller.util.CallerId;
 import net.onrc.onos.ofcontroller.util.DataPath;
@@ -71,9 +75,10 @@
 
     protected GraphDBOperation op;
 
-    protected IRestApiService restApi;
     protected volatile IFloodlightProviderService floodlightProvider;
     protected volatile ITopologyNetService topologyNetService;
+    protected volatile IDatagridService datagridService;
+    protected IRestApiService restApi;
     protected FloodlightModuleContext context;
 
     protected OFMessageDamper messageDamper;
@@ -94,12 +99,6 @@
     private static int nextFlowEntryIdSuffix = 0;
     private static long nextFlowEntryId = 0;
 
-    // State for measurement purpose
-    private static long measurementFlowId = 100000;
-    private static String measurementFlowIdStr = "0x186a0";	// 100000
-    private long modifiedMeasurementFlowTime = 0;
-    //
-
     /** The logger. */
     private static Logger log = LoggerFactory.getLogger(FlowManager.class);
 
@@ -143,10 +142,10 @@
 		    new LinkedList<IFlowEntry>();
 
 		//
-		// Fetch all Flow Entries which need to be updated and select only my Flow Entries
-		// that need to be updated into the switches.
+		// Fetch all Flow Entries which need to be updated and select
+		// only my Flow Entries that need to be updated into the
+		// switches.
 		//
-		boolean processed_measurement_flow = false;
 		Iterable<IFlowEntry> allFlowEntries =
 		    op.getAllSwitchNotUpdatedFlowEntries();
 		for (IFlowEntry flowEntryObj : allFlowEntries) {
@@ -183,15 +182,6 @@
 			addFlowEntries.add(flowEntryObj);
 		    }
 		    counterMyNotUpdatedFlowEntries++;
-		    // Code for measurement purpose
-		    // TODO: Commented-out for now
-		    /*
-		    {
-			if (flowObj.getFlowId().equals(measurementFlowIdStr)) {
-			    processed_measurement_flow = true;
-			}
-		    }
-		    */
 		}
 
 		//
@@ -234,14 +224,6 @@
 
 		op.commit();
 
-		if (processed_measurement_flow) {
-		    long estimatedTime =
-			System.nanoTime() - modifiedMeasurementFlowTime;
-		    String logMsg = "MEASUREMENT: Pushed Flow delay: " +
-			(double)estimatedTime / 1000000000 + " sec";
-		    log.debug(logMsg);
-		}
-
 		long estimatedTime = System.nanoTime() - startTime;
 		double rate = 0.0;
 		if (estimatedTime > 0)
@@ -287,14 +269,11 @@
 		}
 		LinkedList<IFlowPath> deleteFlows = new LinkedList<IFlowPath>();
 
-		boolean processed_measurement_flow = false;
-
 		//
 		// Fetch and recompute the Shortest Path for those
 		// Flow Paths this controller is responsible for.
 		//
-		Map<Long, ?> shortestPathTopo =
-		    topologyNetService.prepareShortestPathTopo();
+		Topology topology = topologyNetService.newDatabaseTopology();
 		Iterable<IFlowPath> allFlowPaths = op.getAllFlowPaths();
 		for (IFlowPath flowPathObj : allFlowPaths) {
 		    counterAllFlowPaths++;
@@ -359,18 +338,19 @@
 		    counterMyFlowPaths++;
 
 		    //
-		    // NOTE: Using here the regular getShortestPath() method
-		    // won't work here, because that method calls internally
-		    //  "conn.endTx(Transaction.COMMIT)", and that will
-		    // invalidate all handlers to the Titan database.
+		    // NOTE: Using here the regular getDatabaseShortestPath()
+		    // method won't work here, because that method calls
+		    // internally "conn.endTx(Transaction.COMMIT)", and that
+		    // will invalidate all handlers to the Titan database.
 		    // If we want to experiment with calling here
-		    // getShortestPath(), we need to refactor that code
+		    // getDatabaseShortestPath(), we need to refactor that code
 		    // to avoid closing the transaction.
 		    //
 		    DataPath dataPath =
-			topologyNetService.getTopoShortestPath(shortestPathTopo,
-							       srcSwitchPort,
-							       dstSwitchPort);
+			topologyNetService.getTopologyShortestPath(
+				topology,
+				srcSwitchPort,
+				dstSwitchPort);
 		    if (dataPath == null) {
 			// We need the DataPath to compare the paths
 			dataPath = new DataPath();
@@ -395,18 +375,10 @@
 		    op.removeFlowPath(flowPathObj);
 		}
 
-		topologyNetService.dropShortestPathTopo(shortestPathTopo);
+		topologyNetService.dropTopology(topology);
 
 		op.commit();
 
-		if (processed_measurement_flow) {
-		    long estimatedTime =
-			System.nanoTime() - modifiedMeasurementFlowTime;
-		    String logMsg = "MEASUREMENT: Pushed Flow delay: " +
-			(double)estimatedTime / 1000000000 + " sec";
-		    log.debug(logMsg);
-		}
-
 		long estimatedTime = System.nanoTime() - startTime;
 		double rate = 0.0;
 		if (estimatedTime > 0)
@@ -429,7 +401,6 @@
     @Override
     public void init(String conf) {
     	op = new GraphDBOperation(conf);
-	topologyNetService = new TopologyManager(conf);
     }
 
     /**
@@ -469,9 +440,9 @@
     public Map<Class<? extends IFloodlightService>, IFloodlightService> 
 			       getServiceImpls() {
         Map<Class<? extends IFloodlightService>,
-        IFloodlightService> m = 
-            new HashMap<Class<? extends IFloodlightService>,
-                IFloodlightService>();
+	    IFloodlightService> m =
+	    new HashMap<Class<? extends IFloodlightService>,
+	    IFloodlightService>();
         m.put(IFlowService.class, this);
         return m;
     }
@@ -483,10 +454,12 @@
      */
     @Override
     public Collection<Class<? extends IFloodlightService>> 
-                                                    getModuleDependencies() {
+				      getModuleDependencies() {
 	Collection<Class<? extends IFloodlightService>> l =
 	    new ArrayList<Class<? extends IFloodlightService>>();
 	l.add(IFloodlightProviderService.class);
+	l.add(INetworkGraphService.class);
+	l.add(IDatagridService.class);
 	l.add(IRestApiService.class);
         return l;
     }
@@ -501,15 +474,16 @@
 	throws FloodlightModuleException {
 	this.context = context;
 	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+	topologyNetService = context.getServiceImpl(ITopologyNetService.class);
+	datagridService = context.getServiceImpl(IDatagridService.class);
 	restApi = context.getServiceImpl(IRestApiService.class);
+
 	messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
 					    EnumSet.of(OFType.FLOW_MOD),
 					    OFMESSAGE_DAMPER_TIMEOUT);
 
-	// TODO: An ugly hack!
-	String conf = "/tmp/cassandra.titan";
-	this.init(conf);
-	
+	this.init("");
+
 	mapReaderScheduler = Executors.newScheduledThreadPool(1);
 	shortestPathReconcileScheduler = Executors.newScheduledThreadPool(1);
     }
@@ -545,10 +519,10 @@
     @Override
     public void startUp(FloodlightModuleContext context) {
 	restApi.addRestletRoutable(new FlowWebRoutable());
-	
+
 	// Initialize the Flow Entry ID generator
 	nextFlowEntryIdPrefix = randomGenerator.nextInt();
-		
+
 	mapReaderScheduler.scheduleAtFixedRate(
 			mapReader, 3, 3, TimeUnit.SECONDS);
 	shortestPathReconcileScheduler.scheduleAtFixedRate(
@@ -570,25 +544,13 @@
     @Override
     public boolean addFlow(FlowPath flowPath, FlowId flowId,
 			   String dataPathSummaryStr) {
-	/*
-	 * TODO: Commented-out for now
-	if (flowPath.flowId().value() == measurementFlowId) {
-	    modifiedMeasurementFlowTime = System.nanoTime();
-	}
-	*/
-
 	IFlowPath flowObj = null;
 	boolean found = false;
 	try {
-	    if ((flowObj = op.searchFlowPath(flowPath.flowId()))
-		!= null) {
-		log.debug("Adding FlowPath with FlowId {}: found existing FlowPath",
-			  flowPath.flowId().toString());
+	    if ((flowObj = op.searchFlowPath(flowPath.flowId())) != null) {
 		found = true;
 	    } else {
 		flowObj = op.newFlowPath();
-		log.debug("Adding FlowPath with FlowId {}: creating new FlowPath",
-			  flowPath.flowId().toString());
 	    }
 	} catch (Exception e) {
 	    // TODO: handle exceptions
@@ -738,13 +700,9 @@
 	try {
 	    if ((flowEntryObj =
 		 op.searchFlowEntry(flowEntry.flowEntryId())) != null) {
-		log.debug("Adding FlowEntry with FlowEntryId {}: found existing FlowEntry",
-			  flowEntry.flowEntryId().toString());
 		found = true;
 	    } else {
 		flowEntryObj = op.newFlowEntry();
-		log.debug("Adding FlowEntry with FlowEntryId {}: creating new FlowEntry",
-			  flowEntry.flowEntryId().toString());
 	    }
 	} catch (Exception e) {
 	    log.error(":addFlow FlowEntryId:{} failed",
@@ -942,13 +900,6 @@
      */
     @Override
     public boolean deleteFlow(FlowId flowId) {
-	/*
-	 * TODO: Commented-out for now
-	if (flowId.value() == measurementFlowId) {
-	    modifiedMeasurementFlowTime = System.nanoTime();
-	}
-	*/
-
 	IFlowPath flowObj = null;
 	//
 	// We just mark the entries for deletion,
@@ -956,14 +907,7 @@
 	// it has been removed from the switches.
 	//
 	try {
-	    if ((flowObj = op.searchFlowPath(flowId))
-		!= null) {
-		log.debug("Deleting FlowPath with FlowId {}: found existing FlowPath",
-			  flowId.toString());
-	    } else {
-		log.debug("Deleting FlowPath with FlowId {}:  FlowPath not found",
-			  flowId.toString());
-	    }
+	    flowObj = op.searchFlowPath(flowId);
 	} catch (Exception e) {
 	    // TODO: handle exceptions
 	    op.rollback();
@@ -1035,14 +979,7 @@
     public boolean clearFlow(FlowId flowId) {
 	IFlowPath flowObj = null;
 	try {
-	    if ((flowObj = op.searchFlowPath(flowId))
-		!= null) {
-		log.debug("Clearing FlowPath with FlowId {}: found existing FlowPath",
-			  flowId.toString());
-	    } else {
-		log.debug("Clearing FlowPath with FlowId {}:  FlowPath not found",
-			  flowId.toString());
-	    }
+	    flowObj = op.searchFlowPath(flowId);
 	} catch (Exception e) {
 	    // TODO: handle exceptions
 	    op.rollback();
@@ -1078,14 +1015,7 @@
     public FlowPath getFlow(FlowId flowId) {
 	IFlowPath flowObj = null;
 	try {
-	    if ((flowObj = op.searchFlowPath(flowId))
-		!= null) {
-		log.debug("Get FlowPath with FlowId {}: found existing FlowPath",
-			  flowId.toString());
-	    } else {
-		log.debug("Get FlowPath with FlowId {}:  FlowPath not found",
-			  flowId.toString());
-	    }
+	    flowObj = op.searchFlowPath(flowId);
 	} catch (Exception e) {
 	    // TODO: handle exceptions
 	    op.rollback();
@@ -1126,10 +1056,8 @@
 	ArrayList<FlowPath> allFlows = getAllFlows();
 	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
 
-	if (allFlows == null) {
-	    log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: no FlowPaths found", installerId, dataPathEndpoints);
+	if (allFlows == null)
 	    return flowPaths;
-	}
 
 	for (FlowPath flow : allFlows) {
 	    //
@@ -1148,12 +1076,6 @@
 	    flowPaths.add(flow);
 	}
 
-	if (flowPaths.isEmpty()) {
-	    log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: no FlowPaths found", installerId, dataPathEndpoints);
-	} else {
-	    log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: FlowPaths are found", installerId, dataPathEndpoints);
-	}
-
 	return flowPaths;
     }
 
@@ -1172,13 +1094,11 @@
 	// We should use the appropriate Titan/Gremlin query to filter-out
 	// the flows as appropriate.
 	//
-    ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-    ArrayList<FlowPath> allFlows = getAllFlows();
+	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
+	ArrayList<FlowPath> allFlows = getAllFlows();
 
-	if (allFlows == null) {
-	    log.debug("Get FlowPaths for dataPathEndpoints{}: no FlowPaths found", dataPathEndpoints);
+	if (allFlows == null)
 	    return flowPaths;
-	}
 
 	for (FlowPath flow : allFlows) {
 	    //
@@ -1195,13 +1115,7 @@
 	    flowPaths.add(flow);
 	}
 
-	if (flowPaths.isEmpty()) {
-	    log.debug("Get FlowPaths for dataPathEndpoints{}: no FlowPaths found", dataPathEndpoints);
-	} else {
-	    log.debug("Get FlowPaths for dataPathEndpoints{}: FlowPaths are found", dataPathEndpoints);
-	}
-
-	return flowPaths;
+return flowPaths;
     }
 
     /**
@@ -1212,7 +1126,8 @@
      * @return the Flow Paths if found, otherwise null.
      */
     @Override
-    public ArrayList<IFlowPath> getAllFlowsSummary(FlowId flowId, int maxFlows) {
+    public ArrayList<IFlowPath> getAllFlowsSummary(FlowId flowId,
+						   int maxFlows) {
 
 	//
 	// TODO: The implementation below is not optimal:
@@ -1221,64 +1136,28 @@
 	// We should use the appropriate Titan/Gremlin query to filter-out
 	// the flows as appropriate.
 	//
-    	//ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-    	
-    	ArrayList<IFlowPath> flowPathsWithoutFlowEntries = getAllFlowsWithoutFlowEntries();
-    	
+    	ArrayList<IFlowPath> flowPathsWithoutFlowEntries =
+	    getAllFlowsWithoutFlowEntries();
+
     	Collections.sort(flowPathsWithoutFlowEntries, 
-    			new Comparator<IFlowPath>(){
-					@Override
-					public int compare(IFlowPath first, IFlowPath second) {
-						// TODO Auto-generated method stub
-						long result = new FlowId(first.getFlowId()).value()
-								- new FlowId(second.getFlowId()).value();
-						if (result > 0) return 1;
-						else if (result < 0) return -1;
-						else return 0;
-					}
-    			}
-    	);
+			 new Comparator<IFlowPath>() {
+			     @Override
+			     public int compare(IFlowPath first, IFlowPath second) {
+				 long result =
+				     new FlowId(first.getFlowId()).value()
+				     - new FlowId(second.getFlowId()).value();
+				 if (result > 0) {
+				     return 1;
+				 } else if (result < 0) {
+				     return -1;
+				 } else {
+				     return 0;
+				 }
+			     }
+			 }
+			 );
     	
     	return flowPathsWithoutFlowEntries;
-    	
-    	/*
-    	ArrayList<FlowPath> allFlows = getAllFlows();
-
-		if (allFlows == null) {
-		    log.debug("Get FlowPathsSummary for {} {}: no FlowPaths found", flowId, maxFlows);
-		    return flowPaths;
-		}
-	
-		Collections.sort(allFlows);
-		
-		for (FlowPath flow : allFlows) {
-		    flow.setFlowEntryMatch(null);
-			
-		    // start from desired flowId
-		    if (flow.flowId().value() < flowId.value()) {
-			continue;
-		    }
-			
-			// Summarize by making null flow entry fields that are not relevant to report
-			for (FlowEntry flowEntry : flow.dataPath().flowEntries()) {
-				flowEntry.setFlowEntryActions(null);
-				flowEntry.setFlowEntryMatch(null);
-			}
-			
-		    flowPaths.add(flow);
-		    if (maxFlows != 0 && flowPaths.size() >= maxFlows) {
-		    	break;
-		    }
-		}
-	
-		if (flowPaths.isEmpty()) {
-		    log.debug("Get FlowPathsSummary {} {}: no FlowPaths found", flowId, maxFlows);
-		} else {
-		    log.debug("Get FlowPathsSummary for {} {}: FlowPaths were found", flowId, maxFlows);
-		}
-	
-		return flowPaths;
-		*/
     }
     
     /**
@@ -1292,11 +1171,7 @@
 	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
 
 	try {
-	    if ((flowPathsObj = op.getAllFlowPaths()) != null) {
-		log.debug("Get all FlowPaths: found FlowPaths");
-	    } else {
-		log.debug("Get all FlowPaths: no FlowPaths found");
-	    }
+	    flowPathsObj = op.getAllFlowPaths();
 	} catch (Exception e) {
 	    // TODO: handle exceptions
 	    op.rollback();
@@ -1330,39 +1205,24 @@
     	Iterable<IFlowPath> flowPathsObj = null;
     	ArrayList<IFlowPath> flowPathsObjArray = new ArrayList<IFlowPath>();
 
+	// TODO: Remove this op.commit() flow, because it is not needed?
     	op.commit();
-    	
+
     	try {
-    	    if ((flowPathsObj = op.getAllFlowPaths()) != null) {
-    		log.debug("Get all FlowPaths: found FlowPaths");
-    	    } else {
-    		log.debug("Get all FlowPaths: no FlowPaths found");
-    	    }
+    	    flowPathsObj = op.getAllFlowPaths();
     	} catch (Exception e) {
     	    // TODO: handle exceptions
     	    op.rollback();
     	    log.error(":getAllFlowPaths failed");
     	}
     	if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
-    	    return new ArrayList<IFlowPath>();	// No Flows found
+    	    return flowPathsObjArray;		// No Flows found
     	}
     	
-    	for (IFlowPath flowObj : flowPathsObj){
-    		flowPathsObjArray.add(flowObj);
-    	}
-    	/*
-    	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-    	for (IFlowPath flowObj : flowPathsObj) {
-    	    //
-    	    // Extract the Flow state
-    	    //
-    	    FlowPath flowPath = extractFlowPath(flowObj);
-    	    if (flowPath != null)
-    		flowPaths.add(flowPath);
-    	}
-    	*/
+    	for (IFlowPath flowObj : flowPathsObj)
+	    flowPathsObjArray.add(flowObj);
 
-    	//conn.endTx(Transaction.COMMIT);
+    	// conn.endTx(Transaction.COMMIT);
 
     	return flowPathsObjArray;
     }
@@ -2318,39 +2178,4 @@
 	//
 	return (installFlowEntry(mySwitch, flowPath, flowEntry));
     }
-
-    /**
-     * Install a Flow Entry on a remote controller.
-     *
-     * TODO: We need it now: Jono
-     * - For now it will make a REST call to the remote controller.
-     * - Internally, it needs to know the name of the remote controller.
-     *
-     * @param flowPath the flow path for the flow entry to install.
-     * @param flowEntry the flow entry to install.
-     * @return true on success, otherwise false.
-     */
-    public boolean installRemoteFlowEntry(FlowPath flowPath,
-					  FlowEntry flowEntry) {
-	// TODO: We need it now: Jono
-	//  - For now it will make a REST call to the remote controller.
-	//  - Internally, it needs to know the name of the remote controller.
-	return true;
-    }
-
-    /**
-     * Remove a flow entry on a remote controller.
-     *
-     * @param flowPath the flow path for the flow entry to remove.
-     * @param flowEntry the flow entry to remove.
-     * @return true on success, otherwise false.
-     */
-    public boolean removeRemoteFlowEntry(FlowPath flowPath,
-					 FlowEntry flowEntry) {
-	//
-	// The installRemoteFlowEntry() method implements both installation
-	// and removal of flow entries.
-	//
-	return (installRemoteFlowEntry(flowPath, flowEntry));
-    }
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java b/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
index bd0ca38..9585366 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
@@ -11,73 +11,72 @@
  */
 public interface ITopologyNetService extends IFloodlightService {
     /**
-     * Get the shortest path from a source to a destination.
-     *
-     * @param src the source in the shortest path computation.
-     * @param dest the destination in the shortest path computation.
-     * @return the data path with the computed shortest path if
-     * found, otherwise null.
-     */
-    DataPath getShortestPath(SwitchPort src, SwitchPort dest);
-
-    /**
      * Fetch the Switch and Ports info from the Titan Graph
      * and return it for fast access during the shortest path
      * computation.
      *
-     * After fetching the state, method @ref getTopoShortestPath()
+     * After fetching the state, method @ref getTopologyShortestPath()
      * can be used for fast shortest path computation.
      *
      * Note: There is certain cost to fetch the state, hence it should
      * be used only when there is a large number of shortest path
      * computations that need to be done on the same topology.
-     * Typically, a single call to @ref prepareShortestPathTopo()
+     * Typically, a single call to @ref newDatabaseTopology()
      * should be followed by a large number of calls to
-     * method @ref getTopoShortestPath().
-     * After the last @ref getTopoShortestPath() call,
-     * method @ref dropShortestPathTopo() should be used to release
+     * method @ref getTopologyShortestPath().
+     * After the last @ref getTopologyShortestPath() call,
+     * method @ref dropTopology() should be used to release
      * the internal state that is not needed anymore:
      *
-     *       Map<Long, ?> shortestPathTopo;
-     *       shortestPathTopo = prepareShortestPathTopo();
+     *       Topology topology = topologyManager.newDatabaseTopology();
      *       for (int i = 0; i < 10000; i++) {
-     *           dataPath = getTopoShortestPath(shortestPathTopo, ...);
+     *           dataPath = topologyManager.getTopologyShortestPath(topology, ...);
      *           ...
      *        }
-     *        dropShortestPathTopo(shortestPathTopo);
+     *        topologyManager.dropTopology(shortestPathTopo);
      *
-     * @return the Shortest Path info handler stored in a map.
+     * @return the allocated topology handler.
      */
-    Map<Long, ?> prepareShortestPathTopo();
+    Topology newDatabaseTopology();
 
     /**
-     * Release the state that was populated by
-     * method @ref prepareShortestPathTopo().
+     * Release the topology that was populated by
+     * method @ref newDatabaseTopology().
      *
-     * See the documentation for method @ref prepareShortestPathTopo()
+     * See the documentation for method @ref newDatabaseTopology()
      * for additional information and usage.
      *
-     * @param shortestPathTopo the Shortest Path info handler to release.
+     * @param topology the topology to release.
      */
-    void dropShortestPathTopo(Map<Long, ?> shortestPathTopo);
+    void dropTopology(Topology topology);
 
     /**
      * Get the shortest path from a source to a destination by
      * using the pre-populated local topology state prepared
-     * by method @ref prepareShortestPathTopo().
+     * by method @ref newDatabaseTopology().
      *
-     * See the documentation for method @ref prepareShortestPathTopo()
+     * See the documentation for method @ref newDatabaseTopology()
      * for additional information and usage.
      *
-     * @param shortestPathTopo the Shortest Path info handler
-     * to use.
+     * @param topology the topology handler to use.
      * @param src the source in the shortest path computation.
      * @param dest the destination in the shortest path computation.
      * @return the data path with the computed shortest path if
      * found, otherwise null.
      */
-    DataPath getTopoShortestPath(Map<Long, ?> shortestPathTopo,
-				 SwitchPort src, SwitchPort dest);
+    DataPath getTopologyShortestPath(Topology topology,
+				     SwitchPort src, SwitchPort dest);
+
+    /**
+     * Get the shortest path from a source to a destination by using
+     * the underlying database.
+     *
+     * @param src the source in the shortest path computation.
+     * @param dest the destination in the shortest path computation.
+     * @return the data path with the computed shortest path if
+     * found, otherwise null.
+     */
+    DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest);
 
     /**
      * Test whether a route exists from a source to a destination.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java b/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
new file mode 100644
index 0000000..1133d3d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
@@ -0,0 +1,325 @@
+package net.onrc.onos.ofcontroller.topology;
+
+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 net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+
+import org.openflow.util.HexString;
+
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Vertex;
+
+/**
+ * A class for implementing the Shortest Path in a topology.
+ */
+public class ShortestPath {
+    /**
+     * Get the shortest path from a source to a destination by
+     * using the pre-populated local topology state prepared
+     * by method @ref TopologyManager.newDatabaseTopology().
+     *
+     * For additional documentation and usage, see method
+     * @ref TopologyManager.newDatabaseTopology()
+     *
+     * @param topology the topology handler to use.
+     * @param src the source in the shortest path computation.
+     * @param dest the destination in the shortest path computation.
+     * @return the data path with the computed shortest path if
+     * found, otherwise null.
+     */
+    public static DataPath getTopologyShortestPath(
+		Topology topology,
+		SwitchPort src, SwitchPort dest) {
+	DataPath result_data_path = new DataPath();
+
+	// Initialize the source and destination in the data path to return
+	result_data_path.setSrcPort(src);
+	result_data_path.setDstPort(dest);
+
+	String dpid_src = src.dpid().toString();
+	String dpid_dest = dest.dpid().toString();
+
+	// Get the source vertex
+	Node v_src = topology.getNode(src.dpid().value());
+	if (v_src == null) {
+	    return null;		// Source vertex not found
+	}
+
+	// Get the destination vertex
+	Node v_dest = topology.getNode(dest.dpid().value());
+	if (v_dest == null) {
+	    return null;		// Destination vertex not found
+	}
+
+	//
+	// Test whether we are computing a path from/to the same DPID.
+	// If "yes", then just add a single flow entry in the return result.
+	//
+	if (dpid_src.equals(dpid_dest)) {
+	    FlowEntry flowEntry = new FlowEntry();
+	    flowEntry.setDpid(src.dpid());
+	    flowEntry.setInPort(src.port());
+	    flowEntry.setOutPort(dest.port());
+	    result_data_path.flowEntries().add(flowEntry);
+	    return result_data_path;
+	}
+
+	//
+	// Implement the Shortest Path computation by using Breath First Search
+	//
+	Set<Node> visitedSet = new HashSet<Node>();
+	Queue<Node> processingList = new LinkedList<Node>();
+	Map<Node, Node.Link> previousVertexMap = new HashMap<Node, Node.Link>();
+	processingList.add(v_src);
+	visitedSet.add(v_src);
+	Boolean path_found = false;
+	while (! processingList.isEmpty()) {
+	    Node nextVertex = processingList.poll();
+	    if (v_dest == nextVertex) {
+		path_found = true;
+		break;
+	    }
+	    for (Node.Link link : nextVertex.links.values()) {
+		Node child = link.neighbor;
+		if (! visitedSet.contains(child)) {
+		    previousVertexMap.put(child, link);
+		    visitedSet.add(child);
+		    processingList.add(child);
+		}
+	    }
+	}
+	if (! path_found)
+	    return null;		// No path found
+
+	// Collect the path as a list of links
+	List<Node.Link> resultPath = new LinkedList<Node.Link>();
+	Node previousVertex = v_dest;
+	while (! v_src.equals(previousVertex)) {
+	    Node.Link currentLink = previousVertexMap.get(previousVertex);
+	    resultPath.add(currentLink);
+	    previousVertex = currentLink.me;
+	}
+	Collections.reverse(resultPath);
+
+	//
+	// Loop through the result and prepare the return result
+	// as a list of Flow Entries.
+	//
+	Port inPort = new Port(src.port().value());
+	Port outPort;
+	for (Node.Link link: resultPath) {
+	    // Setup the outgoing port, and add the Flow Entry
+	    outPort = new Port(link.myPort);
+
+	    FlowEntry flowEntry = new FlowEntry();
+	    flowEntry.setDpid(new Dpid(link.me.nodeId));
+	    flowEntry.setInPort(inPort);
+	    flowEntry.setOutPort(outPort);
+	    result_data_path.flowEntries().add(flowEntry);
+
+	    // Setup the next incoming port
+	    inPort = new Port(link.neighborPort);
+	}
+	if (resultPath.size() > 0) {
+	    // Add the last Flow Entry
+	    FlowEntry flowEntry = new FlowEntry();
+	    flowEntry.setDpid(new Dpid(dest.dpid().value()));
+	    flowEntry.setInPort(inPort);
+	    flowEntry.setOutPort(dest.port());
+	    result_data_path.flowEntries().add(flowEntry);
+	}
+
+	if (result_data_path.flowEntries().size() > 0)
+	    return result_data_path;
+
+	return null;
+    }
+
+    /**
+     * Get the shortest path from a source to a destination by using
+     * the underlying Graph Database.
+     *
+     * @param dbHandler the Graph Database handler to use.
+     * @param src the source in the shortest path computation.
+     * @param dest the destination in the shortest path computation.
+     * @return the data path with the computed shortest path if
+     * found, otherwise null.
+     */
+    public static DataPath getDatabaseShortestPath(GraphDBOperation dbHandler,
+					     SwitchPort src, SwitchPort dest) {
+	DataPath result_data_path = new DataPath();
+
+	// Initialize the source and destination in the data path to return
+	result_data_path.setSrcPort(src);
+	result_data_path.setDstPort(dest);
+
+	String dpid_src = src.dpid().toString();
+	String dpid_dest = dest.dpid().toString();
+
+	// Get the source and destination switches
+	ISwitchObject srcSwitch =
+	    dbHandler.searchActiveSwitch(dpid_src);
+	ISwitchObject destSwitch =
+	    dbHandler.searchActiveSwitch(dpid_dest);
+	if (srcSwitch == null || destSwitch == null) {
+	    return null;
+	}
+
+	//
+	// Test whether we are computing a path from/to the same DPID.
+	// If "yes", then just add a single flow entry in the return result.
+	//
+	if (dpid_src.equals(dpid_dest)) {
+	    FlowEntry flowEntry = new FlowEntry();
+	    flowEntry.setDpid(src.dpid());
+	    flowEntry.setInPort(src.port());
+	    flowEntry.setOutPort(dest.port());
+	    result_data_path.flowEntries().add(flowEntry);
+	    dbHandler.commit();
+	    return result_data_path;
+	}
+
+	Vertex v_src = srcSwitch.asVertex();	
+	Vertex v_dest = destSwitch.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")) {
+		// Ignore inactive ports
+		if (! parentPort.getProperty("state").toString().equals("ACTIVE"))
+			continue;
+
+		for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
+		    // Ignore inactive ports
+		    if (! childPort.getProperty("state").toString().equals("ACTIVE"))
+			continue;
+
+		    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().value());
+	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);
+		result_data_path.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(dest.port());
+	    result_data_path.flowEntries().add(flowEntry);
+	}
+
+	dbHandler.commit();
+	if (result_data_path.flowEntries().size() > 0)
+	    return result_data_path;
+
+	return null;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
new file mode 100644
index 0000000..a2f2c21
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
@@ -0,0 +1,174 @@
+package net.onrc.onos.ofcontroller.topology;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+
+import org.openflow.util.HexString;
+
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Vertex;
+
+/**
+ * A class for storing Node and Link information for fast computation
+ * of shortest paths.
+ */
+class Node {
+    /**
+     * A class for storing Link information for fast computation of shortest
+     * paths.
+     */
+    class Link {
+	public Node me;			// The node this link originates from
+	public Node neighbor;		// The neighbor node on the other side
+	public short myPort;		// Local port number for the link
+	public short neighborPort;	// Neighbor port number for the link
+
+	/**
+	 * Link constructor.
+	 *
+	 * @param me the node this link originates from.
+	 * @param the neighbor node on the other side of the link.
+	 * @param myPort local port number for the link.
+	 * @param neighborPort neighrobr port number for the link.
+	 */
+	public Link(Node me, Node neighbor, short myPort, short neighborPort) {
+	    this.me = me;
+	    this.neighbor = neighbor;
+	    this.myPort = myPort;
+	    this.neighborPort = neighborPort;
+	}
+    };
+
+    public long nodeId;			// The node ID
+    public HashMap<Short, Link> links;	// The links originating from this node
+
+    /**
+     * Node constructor.
+     *
+     * @param nodeId the node ID.
+     */
+    public Node(long nodeId) {
+	this.nodeId = nodeId;
+	links = new HashMap<Short, Link>();
+    }
+
+    /**
+     * Add a neighbor.
+     *
+     * A new link to the neighbor will be created. 
+     *
+     * @param neighbor the neighbor to add.
+     * @param myPort the local port number for the link to the neighbor.
+     * @param neighborPort the neighbor port number for the link.
+     */
+    public void addNeighbor(Node neighbor, short myPort, short neighborPort) {
+	Link link = new Link(this, neighbor, myPort, neighborPort);
+	links.put(myPort, link);
+    }
+};
+
+/**
+ * A class for storing topology information.
+ */
+public class Topology {
+    private Map<Long, Node> nodesMap;	// The dpid->Node mapping
+
+    public Topology() {
+	nodesMap = new HashMap<Long, Node>();
+    }
+
+    /**
+     * Get a node for a give Node ID.
+     *
+     * @param nodeId the Node ID to use.
+     * @return the corresponding Node if found, otherwise null.
+     */
+    Node getNode(long nodeId) {
+	return nodesMap.get(nodeId);
+    }
+
+    /**
+     * Read topology state from the database.
+     *
+     * @param dbHandler the Graph Database handler to use.
+     */
+    public void readFromDatabase(GraphDBOperation dbHandler) {
+	//
+	// Fetch the relevant info from the Switch and Port vertices
+	// from the Titan Graph.
+	//
+	Iterable<ISwitchObject> activeSwitches = dbHandler.getActiveSwitches();
+	for (ISwitchObject switchObj : activeSwitches) {
+	    Vertex nodeVertex = switchObj.asVertex();
+	    //
+	    // The Switch info
+	    //
+	    String nodeDpid = nodeVertex.getProperty("dpid").toString();
+	    long nodeId = HexString.toLong(nodeDpid);
+	    Node me = nodesMap.get(nodeId);
+	    if (me == null) {
+		me = new Node(nodeId);
+		nodesMap.put(nodeId, me);
+	    }
+
+	    //
+	    // The local Port info
+	    //
+	    for (Vertex myPortVertex : nodeVertex.getVertices(Direction.OUT, "on")) {
+		// Ignore inactive ports
+		if (! myPortVertex.getProperty("state").toString().equals("ACTIVE"))
+		    continue;
+
+		short myPort = 0;
+		Object obj = myPortVertex.getProperty("number");
+		if (obj instanceof Short) {
+		    myPort = (Short)obj;
+		} else if (obj instanceof Integer) {
+		    Integer int_nodeId = (Integer)obj;
+		    myPort = int_nodeId.shortValue();
+		}
+
+		//
+		// The neighbor Port info
+		//
+		for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
+		    // Ignore inactive ports
+		    if (! neighborPortVertex.getProperty("state").toString().equals("ACTIVE"))
+			continue;
+
+		    short neighborPort = 0;
+		    obj = neighborPortVertex.getProperty("number");
+		    if (obj instanceof Short) {
+			neighborPort = (Short)obj;
+		    } else if (obj instanceof Integer) {
+			Integer int_nodeId = (Integer)obj;
+			neighborPort = int_nodeId.shortValue();
+		    }
+		    //
+		    // The neighbor Switch info
+		    //
+		    for (Vertex neighborVertex : neighborPortVertex.getVertices(Direction.IN, "on")) {
+			// Ignore inactive switches
+			String state = neighborVertex.getProperty("state").toString();
+			if (! state.equals(SwitchState.ACTIVE.toString()))
+			    continue;
+
+			String neighborDpid = neighborVertex.getProperty("dpid").toString();
+			long neighborId = HexString.toLong(neighborDpid);
+			Node neighbor = nodesMap.get(neighborId);
+			if (neighbor == null) {
+			    neighbor = new Node(neighborId);
+			    nodesMap.put(neighborId, neighbor);
+			}
+			me.addNeighbor(neighbor, myPort, neighborPort);
+		    }
+		}
+	    }
+	}
+	dbHandler.commit();
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
index 618ae39..81ff599 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
@@ -1,99 +1,34 @@
 package net.onrc.onos.ofcontroller.topology;
 
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.Collection;
 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 net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+import net.onrc.onos.datagrid.IDatagridService;
 import net.onrc.onos.graph.GraphDBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
 import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.Port;
 import net.onrc.onos.ofcontroller.util.SwitchPort;
 
-import org.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Vertex;
-
-
-/**
- * A class for storing Node and Link information for fast computation
- * of shortest paths.
- */
-class Node {
-    /**
-     * A class for storing Link information for fast computation of shortest
-     * paths.
-     */
-    class Link {
-	public Node me;			// The node this link originates from
-	public Node neighbor;		// The neighbor node on the other side
-	public short myPort;		// Local port number for the link
-	public short neighborPort;	// Neighbor port number for the link
-
-	/**
-	 * Link constructor.
-	 *
-	 * @param me the node this link originates from.
-	 * @param the neighbor node on the other side of the link.
-	 * @param myPort local port number for the link.
-	 * @param neighborPort neighrobr port number for the link.
-	 */
-	public Link(Node me, Node neighbor, short myPort, short neighborPort) {
-	    this.me = me;
-	    this.neighbor = neighbor;
-	    this.myPort = myPort;
-	    this.neighborPort = neighborPort;
-	}
-    };
-
-    public long nodeId;			// The node ID
-    public HashMap<Short, Link> links;	// The links originating from this node
-
-    /**
-     * Node constructor.
-     *
-     * @param nodeId the node ID.
-     */
-    public Node(long nodeId) {
-	this.nodeId = nodeId;
-	links = new HashMap<Short, Link>();
-    }
-
-    /**
-     * Add a neighbor.
-     *
-     * A new link to the neighbor will be created. 
-     *
-     * @param neighbor the neighbor to add.
-     * @param myPort the local port number for the link to the neighbor.
-     * @param neighborPort the neighbor port number for the link.
-     */
-    public void addNeighbor(Node neighbor, short myPort, short neighborPort) {
-	Link link = new Link(this, neighbor, myPort, neighborPort);
-	links.put(myPort, link);
-    }
-};
-
 /**
  * A class for implementing Topology Network Service.
  */
-public class TopologyManager implements ITopologyNetService {
-
-    /** The logger. */
+public class TopologyManager implements IFloodlightModule,
+					ITopologyNetService {
     private static Logger log = LoggerFactory.getLogger(TopologyManager.class);
-    
-    protected GraphDBOperation op;
+    protected IFloodlightProviderService floodlightProvider;
+
+    protected GraphDBOperation dbHandler;
 
 
     /**
@@ -113,6 +48,16 @@
     }
 
     /**
+     * Constructor for a given database operation handler.
+     *
+     * @param dbHandler the database operation handler to use for the
+     * initialization.
+     */
+    public TopologyManager(GraphDBOperation dbHandler) {
+	this.dbHandler = dbHandler;
+    }
+
+    /**
      * Init the module.
      *
      * @param config the database configuration file to use for
@@ -120,27 +65,93 @@
      */
     public void init(String config) {
 	try {
-	    op = new GraphDBOperation(config);
+	    dbHandler = new GraphDBOperation(config);
 	} catch (Exception e) {
 	    log.error(e.getMessage());
 	}
     }
 
     /**
-     * Close the service. It will close the corresponding database connection.
+     * Shutdown the Topology Manager operation.
      */
-    public void close() {
-	op.close();
+    public void finalize() {
+	close();
     }
 
     /**
-     * Set the database operation handler.
-     *
-     * @param init_op the database operation handler to use for the
-     * initialization.
+     * Close the service. It will close the corresponding database connection.
      */
-    public void setDbOperationHandler(GraphDBOperation init_op) {
-    	op = init_op;
+    public void close() {
+	dbHandler.close();
+    }
+
+    /**
+     * Get the collection of offered module services.
+     *
+     * @return the collection of offered module services.
+     */
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+        Collection<Class<? extends IFloodlightService>> l = 
+            new ArrayList<Class<? extends IFloodlightService>>();
+        l.add(ITopologyNetService.class);
+        return l;
+    }
+
+    /**
+     * Get the collection of implemented services.
+     *
+     * @return the collection of implemented services.
+     */
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService> 
+			       getServiceImpls() {
+        Map<Class<? extends IFloodlightService>,
+	    IFloodlightService> m = 
+            new HashMap<Class<? extends IFloodlightService>,
+	    IFloodlightService>();
+        m.put(ITopologyNetService.class, this);
+        return m;
+    }
+
+    /**
+     * Get the collection of modules this module depends on.
+     *
+     * @return the collection of modules this module depends on.
+     */
+    @Override
+    public Collection<Class<? extends IFloodlightService>> 
+                                                    getModuleDependencies() {
+	Collection<Class<? extends IFloodlightService>> l =
+	    new ArrayList<Class<? extends IFloodlightService>>();
+	l.add(IFloodlightProviderService.class);
+	l.add(INetworkGraphService.class);
+	l.add(IDatagridService.class);
+        return l;
+    }
+
+    /**
+     * Initialize the module.
+     *
+     * @param context the module context to use for the initialization.
+     */
+    @Override
+    public void init(FloodlightModuleContext context)
+	throws FloodlightModuleException {
+	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+
+	String conf = "";
+	this.init(conf);
+    }
+
+    /**
+     * Startup module operation.
+     *
+     * @param context the module context to use for the startup.
+     */
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+
     }
 
     /**
@@ -148,248 +159,70 @@
      * and return it for fast access during the shortest path
      * computation.
      *
-     * After fetching the state, method @ref getTopoShortestPath()
+     * After fetching the state, method @ref getTopologyShortestPath()
      * can be used for fast shortest path computation.
      *
      * Note: There is certain cost to fetch the state, hence it should
      * be used only when there is a large number of shortest path
      * computations that need to be done on the same topology.
-     * Typically, a single call to @ref prepareShortestPathTopo()
+     * Typically, a single call to @ref newDatabaseTopology()
      * should be followed by a large number of calls to
-     * method @ref getTopoShortestPath().
-     * After the last @ref getTopoShortestPath() call,
-     * method @ref dropShortestPathTopo() should be used to release
+     * method @ref getTopologyShortestPath().
+     * After the last @ref getTopologyShortestPath() call,
+     * method @ref dropTopology() should be used to release
      * the internal state that is not needed anymore:
      *
-     *       Map<Long, ?> shortestPathTopo;
-     *       shortestPathTopo = prepareShortestPathTopo();
+     *       Topology topology = topologyManager.newDatabaseTopology();
      *       for (int i = 0; i < 10000; i++) {
-     *           dataPath = getTopoShortestPath(shortestPathTopo, ...);
+     *           dataPath = topologyManager.getTopologyShortestPath(topology, ...);
      *           ...
      *        }
-     *        dropShortestPathTopo(shortestPathTopo);
+     *        topologyManager.dropTopology(shortestPathTopo);
      *
-     * @return the Shortest Path info handler stored in a map.
+     * @return the allocated topology handler.
      */
-    public Map<Long, ?> prepareShortestPathTopo() {
-	Map<Long, Node> shortestPathTopo = new HashMap<Long, Node>();
+    public Topology newDatabaseTopology() {
+	Topology topology = new Topology();
+	topology.readFromDatabase(dbHandler);
 
-	//
-	// Fetch the relevant info from the Switch and Port vertices
-	// from the Titan Graph.
-	//
-	Iterable<ISwitchObject> nodes = op.getActiveSwitches();
-	for (ISwitchObject switchObj : nodes) {
-	    Vertex nodeVertex = switchObj.asVertex();
-	    //
-	    // The Switch info
-	    //
-	    String nodeDpid = nodeVertex.getProperty("dpid").toString();
-	    long nodeId = HexString.toLong(nodeDpid);
-	    Node me = shortestPathTopo.get(nodeId);
-	    if (me == null) {
-		me = new Node(nodeId);
-		shortestPathTopo.put(nodeId, me);
-	    }
-
-	    //
-	    // The local Port info
-	    //
-	    for (Vertex myPortVertex : nodeVertex.getVertices(Direction.OUT, "on")) {
-		// Ignore inactive ports
-		if (! myPortVertex.getProperty("state").toString().equals("ACTIVE"))
-		    continue;
-
-		short myPort = 0;
-		Object obj = myPortVertex.getProperty("number");
-		if (obj instanceof Short) {
-		    myPort = (Short)obj;
-		} else if (obj instanceof Integer) {
-		    Integer int_nodeId = (Integer)obj;
-		    myPort = int_nodeId.shortValue();
-		}
-
-		//
-		// The neighbor Port info
-		//
-		for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
-		    // Ignore inactive ports
-		    if (! neighborPortVertex.getProperty("state").toString().equals("ACTIVE"))
-			continue;
-
-		    short neighborPort = 0;
-		    obj = neighborPortVertex.getProperty("number");
-		    if (obj instanceof Short) {
-			neighborPort = (Short)obj;
-		    } else if (obj instanceof Integer) {
-			Integer int_nodeId = (Integer)obj;
-			neighborPort = int_nodeId.shortValue();
-		    }
-		    //
-		    // The neighbor Switch info
-		    //
-		    for (Vertex neighborVertex : neighborPortVertex.getVertices(Direction.IN, "on")) {
-			// Ignore inactive switches
-			String state = neighborVertex.getProperty("state").toString();
-			if (! state.equals(SwitchState.ACTIVE.toString()))
-			    continue;
-
-			String neighborDpid = neighborVertex.getProperty("dpid").toString();
-			long neighborId = HexString.toLong(neighborDpid);
-			Node neighbor = shortestPathTopo.get(neighborId);
-			if (neighbor == null) {
-			    neighbor = new Node(neighborId);
-			    shortestPathTopo.put(neighborId, neighbor);
-			}
-			me.addNeighbor(neighbor, myPort, neighborPort);
-		    }
-		}
-	    }
-	}
-	op.commit();
-
-	return shortestPathTopo;
+	return topology;
     }
 
     /**
-     * Release the state that was populated by
-     * method @ref prepareShortestPathTopo().
+     * Release the topology that was populated by
+     * method @ref newDatabaseTopology().
      *
-     * See the documentation for method @ref prepareShortestPathTopo()
+     * See the documentation for method @ref newDatabaseTopology()
      * for additional information and usage.
      *
-     * @param shortestPathTopo the Shortest Path info handler to release.
+     * @param topology the topology to release.
      */
-    public void dropShortestPathTopo(Map<Long, ?> shortestPathTopo) {
-	shortestPathTopo = null;
+    public void dropTopology(Topology topology) {
+	topology = null;
     }
 
     /**
      * Get the shortest path from a source to a destination by
      * using the pre-populated local topology state prepared
-     * by method @ref prepareShortestPathTopo().
+     * by method @ref newDatabaseTopology().
      *
-     * See the documentation for method @ref prepareShortestPathTopo()
+     * See the documentation for method @ref newDatabaseTopology()
      * for additional information and usage.
      *
-     * @param shortestPathTopoHandler the Shortest Path info handler
-     * to use.
+     * @param topology the topology handler to use.
      * @param src the source in the shortest path computation.
      * @param dest the destination in the shortest path computation.
      * @return the data path with the computed shortest path if
      * found, otherwise null.
      */
-    public DataPath getTopoShortestPath(Map<Long, ?> shortestPathTopoHandler,
-					SwitchPort src, SwitchPort dest) {
-	@SuppressWarnings("unchecked")
-	Map<Long, Node> shortestPathTopo = (Map<Long, Node>)shortestPathTopoHandler;
-	DataPath result_data_path = new DataPath();
-
-	// Initialize the source and destination in the data path to return
-	result_data_path.setSrcPort(src);
-	result_data_path.setDstPort(dest);
-
-	String dpid_src = src.dpid().toString();
-	String dpid_dest = dest.dpid().toString();
-
-	// Get the source vertex
-	Node v_src = shortestPathTopo.get(src.dpid().value());
-	if (v_src == null) {
-	    return null;		// Source vertex not found
-	}
-
-	// Get the destination vertex
-	Node v_dest = shortestPathTopo.get(dest.dpid().value());
-	if (v_dest == null) {
-	    return null;		// Destination vertex not found
-	}
-
-	//
-	// Test whether we are computing a path from/to the same DPID.
-	// If "yes", then just add a single flow entry in the return result.
-	//
-	if (dpid_src.equals(dpid_dest)) {
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(src.dpid());
-	    flowEntry.setInPort(src.port());
-	    flowEntry.setOutPort(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	    return result_data_path;
-	}
-
-	//
-	// Implement the Shortest Path computation by using Breath First Search
-	//
-	Set<Node> visitedSet = new HashSet<Node>();
-	Queue<Node> processingList = new LinkedList<Node>();
-	Map<Node, Node.Link> previousVertexMap = new HashMap<Node, Node.Link>();
-	processingList.add(v_src);
-	visitedSet.add(v_src);
-	Boolean path_found = false;
-	while (! processingList.isEmpty()) {
-	    Node nextVertex = processingList.poll();
-	    if (v_dest == nextVertex) {
-		path_found = true;
-		break;
-	    }
-	    for (Node.Link link : nextVertex.links.values()) {
-		Node child = link.neighbor;
-		if (! visitedSet.contains(child)) {
-		    previousVertexMap.put(child, link);
-		    visitedSet.add(child);
-		    processingList.add(child);
-		}
-	    }
-	}
-	if (! path_found)
-	    return null;		// No path found
-
-	// Collect the path as a list of links
-	List<Node.Link> resultPath = new LinkedList<Node.Link>();
-	Node previousVertex = v_dest;
-	while (! v_src.equals(previousVertex)) {
-	    Node.Link currentLink = previousVertexMap.get(previousVertex);
-	    resultPath.add(currentLink);
-	    previousVertex = currentLink.me;
-	}
-	Collections.reverse(resultPath);
-
-	//
-	// Loop through the result and prepare the return result
-	// as a list of Flow Entries.
-	//
-	Port inPort = new Port(src.port().value());
-	Port outPort;
-	for (Node.Link link: resultPath) {
-	    // Setup the outgoing port, and add the Flow Entry
-	    outPort = new Port(link.myPort);
-
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(new Dpid(link.me.nodeId));
-	    flowEntry.setInPort(inPort);
-	    flowEntry.setOutPort(outPort);
-	    result_data_path.flowEntries().add(flowEntry);
-
-	    // Setup the next incoming port
-	    inPort = new Port(link.neighborPort);
-	}
-	if (resultPath.size() > 0) {
-	    // Add the last Flow Entry
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(new Dpid(dest.dpid().value()));
-	    flowEntry.setInPort(inPort);
-	    flowEntry.setOutPort(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	}
-
-	if (result_data_path.flowEntries().size() > 0)
-	    return result_data_path;
-
-	return null;
+    public DataPath getTopologyShortestPath(Topology topology,
+					    SwitchPort src, SwitchPort dest) {
+	return ShortestPath.getTopologyShortestPath(topology, src, dest);
     }
 
     /**
-     * Get the shortest path from a source to a destination.
+     * Get the shortest path from a source to a destination by using
+     * the underlying database.
      *
      * @param src the source in the shortest path computation.
      * @param dest the destination in the shortest path computation.
@@ -397,167 +230,8 @@
      * found, otherwise null.
      */
     @Override
-    public DataPath getShortestPath(SwitchPort src, SwitchPort dest) {
-	DataPath result_data_path = new DataPath();
-
-	// Initialize the source and destination in the data path to return
-	result_data_path.setSrcPort(src);
-	result_data_path.setDstPort(dest);
-
-	String dpid_src = src.dpid().toString();
-	String dpid_dest = dest.dpid().toString();
-
-	// Get the source and destination switches
-	ISwitchObject srcSwitch =
-	    op.searchActiveSwitch(dpid_src);
-	ISwitchObject destSwitch =
-	    op.searchActiveSwitch(dpid_dest);
-	if (srcSwitch == null || destSwitch == null) {
-	    return null;
-	}
-
-	//
-	// Test whether we are computing a path from/to the same DPID.
-	// If "yes", then just add a single flow entry in the return result.
-	//
-	if (dpid_src.equals(dpid_dest)) {
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(src.dpid());
-	    flowEntry.setInPort(src.port());
-	    flowEntry.setOutPort(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	    op.commit();
-	    return result_data_path;
-	}
-
-	Vertex v_src = srcSwitch.asVertex();	
-	Vertex v_dest = destSwitch.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")) {
-		// Ignore inactive ports
-		if (! parentPort.getProperty("state").toString().equals("ACTIVE"))
-			continue;
-
-		for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
-		    // Ignore inactive ports
-		    if (! childPort.getProperty("state").toString().equals("ACTIVE"))
-			continue;
-
-		    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().value());
-	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);
-		result_data_path.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(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	}
-
-	op.commit();
-	if (result_data_path.flowEntries().size() > 0)
-	    return result_data_path;
-
-	return null;
+    public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
+	return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
     }
 
     /**
@@ -569,7 +243,7 @@
      */
     @Override
     public Boolean routeExists(SwitchPort src, SwitchPort dest) {
-	DataPath dataPath = getShortestPath(src, dest);
+	DataPath dataPath = getDatabaseShortestPath(src, dest);
 	return (dataPath != null);
     }
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
index a730719..1cb39b3 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
@@ -37,8 +37,9 @@
 	Port dstPort = new Port(Short.parseShort(dstPortStr));
         
 	DataPath result =
-	    topologyNetService.getShortestPath(new SwitchPort(srcDpid, srcPort),
-					       new SwitchPort(dstDpid, dstPort));
+	    topologyNetService.getDatabaseShortestPath(
+		new SwitchPort(srcDpid, srcPort),
+		new SwitchPort(dstDpid, dstPort));
 	if (result != null) {
 	    return result;
 	} else {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
index e807b56..7c6597d 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
@@ -105,8 +105,8 @@
      * computation.
      *
      * NOTE: This method assumes the DataPath was created by
-     * using FlowManager::getShortestPath() so the inPort and outPort
-     * of the Flow Entries are set.
+     * using the TopologyManager shortest path computation, so the inPort
+     * and outPort of the Flow Entries are set.
      * NOTE: This method is a temporary solution and will be removed
      * in the future.
      *
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
index 5a1549b..db82825 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
@@ -696,7 +696,7 @@
 
 		// verify the test
 		verifyAll();
-		assertEquals(2, md.size());
+		assertEquals(4, md.size());
 		assertTrue(md.contains(IFloodlightProviderService.class));
 		assertTrue(md.contains(IRestApiService.class));
 	}
@@ -976,22 +976,4 @@
 	public final void testRemoveFlowEntrySuccessNormally() {
 		fail("not yet implemented");
 	}
-
-	/**
-	 * Test method for {@link FlowManager#installRemoteFlowEntry(FlowPath, FlowEntry)}.
-	 * The method seems to be not implemented and not used for now.
-	 */
-	@Ignore @Test
-	public final void testInstallRemoteFlowEntrySuccessNormally() {
-		fail("not yet implemented");
-	}
-
-	/**
-	 * Test method for {@link FlowManager#removeRemoteFlowEntry(FlowPath, FlowEntry)}.
-	 * The method seems to be not implemented and not used for now.
-	 */
-	@Ignore @Test
-	public final void testRemoveRemoteFlowEntrySuccessNormally() {
-		fail("not yet implemented");
-	}
 }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
index fbec59e..09d0a00 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
@@ -64,8 +64,7 @@
 	TestDatabaseManager.populateTestData(titanGraph);
 
 	// Prepare the TopologyManager instance
-	topologyManager = new TopologyManager();
-	topologyManager.setDbOperationHandler(oper);
+	topologyManager = new TopologyManager(oper);
     }
 
     /**
@@ -78,12 +77,12 @@
     }
 
     /**
-     * Test method TopologyManager.getTopoShortestPath()
+     * Test method TopologyManager.getTopologyShortestPath()
      *
-     * @see net.onrc.onos.ofcontroller.topology.TopologyManager#getTopoShortestPath
+     * @see net.onrc.onos.ofcontroller.topology.TopologyManager#getTopologyShortestPath
      */
     @Test
-    public void test_getTopoShortestPath() {
+    public void test_getTopologyShortestPath() {
 	DataPath dataPath = null;
 	String srcDpidStr = "00:00:00:00:00:00:0a:01";
 	String dstDpidStr = "00:00:00:00:00:00:0a:06";
@@ -103,11 +102,10 @@
 	//
 	// Test a valid Shortest-Path computation
 	//
-	Map<Long, ?> shortestPathTopo =
-	    topologyManager.prepareShortestPathTopo();
-	dataPath = topologyManager.getTopoShortestPath(shortestPathTopo,
-						       srcSwitchPort,
-						       dstSwitchPort);
+	Topology topology = topologyManager.newDatabaseTopology();
+	dataPath = topologyManager.getTopologyShortestPath(topology,
+							   srcSwitchPort,
+							   dstSwitchPort);
 	assertTrue(dataPath != null);
 	String dataPathSummaryStr = dataPath.dataPathSummary();
 	// System.out.println(dataPathSummaryStr);
@@ -134,21 +132,21 @@
 	String noSuchDpidStr = "ff:ff:00:00:00:00:0a:06";
 	Dpid noSuchDstDpid = new Dpid(noSuchDpidStr);
 	SwitchPort noSuchDstSwitchPort = new SwitchPort(noSuchDstDpid, dstPort);
-	dataPath = topologyManager.getTopoShortestPath(shortestPathTopo,
-						       srcSwitchPort,
-						       noSuchDstSwitchPort);
+	dataPath = topologyManager.getTopologyShortestPath(topology,
+							   srcSwitchPort,
+							   noSuchDstSwitchPort);
 	assertTrue(dataPath == null);
 
-	topologyManager.dropShortestPathTopo(shortestPathTopo);
+	topologyManager.dropTopology(topology);
     }
 
     /**
-     * Test method TopologyManager.getShortestPath()
+     * Test method TopologyManager.getDatabaseShortestPath()
      *
-     * @see net.onrc.onos.ofcontroller.routing.TopologyManager#getShortestPath
+     * @see net.onrc.onos.ofcontroller.routing.TopologyManager#getDatabaseShortestPath
      */
     @Test
-    public void test_getShortestPath() {
+    public void test_getDatabaseShortestPath() {
 	DataPath dataPath = null;
 	String srcDpidStr = "00:00:00:00:00:00:0a:01";
 	String dstDpidStr = "00:00:00:00:00:00:0a:06";
@@ -168,8 +166,8 @@
 	//
 	// Test a valid Shortest-Path computation
 	//
-	dataPath = topologyManager.getShortestPath(srcSwitchPort,
-						   dstSwitchPort);
+	dataPath = topologyManager.getDatabaseShortestPath(srcSwitchPort,
+							   dstSwitchPort);
 	assertTrue(dataPath != null);
 	String dataPathSummaryStr = dataPath.dataPathSummary();
 	// System.out.println(dataPathSummaryStr);
@@ -197,8 +195,8 @@
 	Dpid noSuchDstDpid = new Dpid(noSuchDpidStr);
 	SwitchPort noSuchDstSwitchPort = new SwitchPort(noSuchDstDpid, dstPort);
 
-	dataPath = topologyManager.getShortestPath(srcSwitchPort,
-						   noSuchDstSwitchPort);
+	dataPath = topologyManager.getDatabaseShortestPath(srcSwitchPort,
+							   noSuchDstSwitchPort);
 	assertTrue(dataPath == null);
     }