Implement the periodic shortest path computation and triggering of
the flow path reconciliation.

For now, the computation code and the trigger itself are commented-out.
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 25cf367..ba87666 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -263,7 +263,6 @@
 		    log.debug("FloodlightProvider service not found!");
 		    return;
 		}
-
 		Map<Long, IOFSwitch> mySwitches =
 		    floodlightProvider.getSwitches();
 		Map<Long, IFlowEntry> myFlowEntries =
@@ -272,6 +271,77 @@
 		    new LinkedList<IFlowEntry>();
 
 		//
+		// Fetch and recompute the Shortest Path for those
+		// Flow Paths this controller is responsible for.
+		//
+
+		/*
+		 * TODO: For now, the computation of the reconciliation is
+		 * commented-out.
+		 */
+		/*
+		topoRouteService.prepareShortestPathTopo();
+		Iterable<IFlowPath> allFlowPaths = conn.utils().getAllFlowPaths(conn);
+		HashSet<IFlowPath> flowObjSet = new HashSet<IFlowPath>();
+		for (IFlowPath flowPathObj : allFlowPaths) {
+		    if (flowPathObj == null)
+			continue;
+		    String dataPathSummaryStr = flowPathObj.getDataPathSummary();
+		    if (dataPathSummaryStr == null)
+			continue;	// Could be invalid entry?
+		    if (dataPathSummaryStr.isEmpty())
+			continue;	// No need to maintain this flow
+
+		    // Fetch the fields needed to recompute the shortest path
+		    String flowIdStr = flowPathObj.getFlowId();
+		    String srcDpidStr = flowPathObj.getSrcSwitch();
+		    Short srcPortShort = flowPathObj.getSrcPort();
+		    String dstDpidStr = flowPathObj.getDstSwitch();
+		    Short dstPortShort = flowPathObj.getDstPort();
+		    if ((flowIdStr == null) ||
+			(srcDpidStr == null) ||
+			(srcPortShort == null) ||
+			(dstDpidStr == null) ||
+			(dstPortShort == null)) {
+			log.debug("IGNORING Flow Path entry with null fields");
+			continue;
+		    }
+
+		    FlowId flowId = new FlowId(flowIdStr);
+		    Dpid srcDpid = new Dpid(srcDpidStr);
+		    Port srcPort = new Port(srcPortShort);
+		    Dpid dstDpid = new Dpid(dstDpidStr);
+		    Port dstPort = new Port(dstPortShort);
+		    SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
+		    SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
+		    DataPath dataPath =
+			topoRouteService.getTopoShortestPath(srcSwitchPort,
+							     dstSwitchPort);
+		    String newDataPathSummaryStr = dataPath.dataPathSummary();
+		    if (dataPathSummaryStr.equals(newDataPathSummaryStr))
+			continue;	// Nothing changed
+
+		    //
+		    // Use the source DPID as a heuristic to decide
+		    // which controller is responsible for maintaining the
+		    // shortest path.
+		    // NOTE: This heuristic is error-prone: if the switch
+		    // goes away and no controller is responsible for that
+		    // switch, then the original Flow Path is not cleaned-up
+		    //
+		    IOFSwitch mySwitch = mySwitches.get(srcDpid.value());
+		    if (mySwitch == null)
+			continue;	// Ignore: not my responsibility
+
+		    log.debug("RECONCILE: Need to Reconcile Shortest Path for FlowID {}",
+			      flowId.toString());
+		    flowObjSet.add(flowPathObj);
+		}
+		reconcileFlows(flowObjSet);
+		topoRouteService.dropShortestPathTopo();
+		*/
+
+		//
 		// Fetch all Flow Entries and select only my Flow Entries
 		// that need to be undated into the switches.
 		//
@@ -593,10 +663,13 @@
      *
      * @param flowPath the Flow Path to install.
      * @param flowId the return-by-reference Flow ID as assigned internally.
+     * @param dataPathSummaryStr the data path summary string if the added
+     * flow will be maintained internally, otherwise null.
      * @return true on success, otherwise false.
      */
     @Override
-    public boolean addFlow(FlowPath flowPath, FlowId flowId) {
+    public boolean addFlow(FlowPath flowPath, FlowId flowId,
+			   String dataPathSummaryStr) {
 	if (flowPath.flowId().value() == measurementFlowId) {
 	    modifiedMeasurementFlowTime = System.nanoTime();
 	}
@@ -654,6 +727,12 @@
 	flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
 	flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
 
+	if (dataPathSummaryStr != null) {
+	    flowObj.setDataPathSummary(dataPathSummaryStr);
+	} else {
+	    flowObj.setDataPathSummary("");
+	}
+
 	// Flow edges:
 	//   HeadFE
 
@@ -1125,16 +1204,16 @@
 	String flowIdStr = flowObj.getFlowId();
 	String installerIdStr = flowObj.getInstallerId();
 	String srcSwitchStr = flowObj.getSrcSwitch();
-	Short srcPortStr = flowObj.getSrcPort();
+	Short srcPortShort = flowObj.getSrcPort();
 	String dstSwitchStr = flowObj.getDstSwitch();
-	Short dstPortStr = flowObj.getDstPort();
+	Short dstPortShort = flowObj.getDstPort();
 
 	if ((flowIdStr == null) ||
 	    (installerIdStr == null) ||
 	    (srcSwitchStr == null) ||
-	    (srcPortStr == null) ||
+	    (srcPortShort == null) ||
 	    (dstSwitchStr == null) ||
-	    (dstPortStr == null)) {
+	    (dstPortShort == null)) {
 	    // TODO: A work-around, becauuse of some bogus database objects
 	    return null;
 	}
@@ -1142,9 +1221,9 @@
 	flowPath.setFlowId(new FlowId(flowIdStr));
 	flowPath.setInstallerId(new CallerId(installerIdStr));
 	flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
-	flowPath.dataPath().srcPort().setPort(new Port(srcPortStr));
+	flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
 	flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
-	flowPath.dataPath().dstPort().setPort(new Port(dstPortStr));
+	flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
 
 	//
 	// Extract all Flow Entries
@@ -1229,6 +1308,8 @@
      */
     @Override
     public FlowPath addAndMaintainShortestPathFlow(FlowPath flowPath) {
+	String dataPathSummaryStr = null;
+
 	//
 	// Do the shortest path computation
 	//
@@ -1243,6 +1324,9 @@
 	    userFlowEntryMatch = flowPath.dataPath().flowEntries().get(0).flowEntryMatch();
 	}
 
+	// Compute the Data Path summary
+	dataPathSummaryStr = dataPath.dataPathSummary();
+
 	//
 	// Set the incoming port matching and the outgoing port output
 	// actions for each flow entry.
@@ -1277,7 +1361,7 @@
 	computedFlowPath.setDataPath(dataPath);
 
 	FlowId flowId = new FlowId();
-	if (! addFlow(computedFlowPath, flowId))
+	if (! addFlow(computedFlowPath, flowId, dataPathSummaryStr))
 	    return null;
 
 	// TODO: Mark the flow for maintenance purpose
@@ -1352,21 +1436,37 @@
 	    if (flowObj != null)
 		flowObjSet.add(flowObj);
 	}
-	// conn.endTx(Transaction.COMMIT);
+
+	// Reconcile the affected flows
+	reconcileFlows(flowObjSet);
+    }
+
+    /**
+     * Reconcile all flows in a set.
+     *
+     * @param flowObjSet the set of flows that need to be reconciliated.
+     */
+    public void reconcileFlows(Iterable<IFlowPath> flowObjSet) {
+	if (! flowObjSet.iterator().hasNext())
+	    return;
 
 	//
 	// Remove the old Flow Entries, and add the new Flow Entries
 	//
+
 	Map<Long, IOFSwitch> mySwitches = floodlightProvider.getSwitches();
+	LinkedList<FlowPath> flowPaths = new LinkedList<FlowPath>();
 	for (IFlowPath flowObj : flowObjSet) {
 	    FlowPath flowPath = extractFlowPath(flowObj);
 	    if (flowPath == null)
 		continue;
+	    flowPaths.add(flowPath);
 
 	    //
 	    // Remove my Flow Entries from the Network MAP
 	    //
 	    Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+	    LinkedList<IFlowEntry> deleteFlowEntries = new LinkedList<IFlowEntry>();
 	    for (IFlowEntry flowEntryObj : flowEntries) {
 		String dpidStr = flowEntryObj.getSwitchDpid();
 		if (dpidStr == null)
@@ -1375,10 +1475,15 @@
 		IOFSwitch mySwitch = mySwitches.get(dpid.value());
 		if (mySwitch == null)
 		    continue;		// Ignore the entry: not my switch
+		deleteFlowEntries.add(flowEntryObj);
+	    }
+	    for (IFlowEntry flowEntryObj : deleteFlowEntries) {
 		flowObj.removeFlowEntry(flowEntryObj);
 		conn.utils().removeFlowEntry(conn, flowEntryObj);
 	    }
+	}
 
+	for (FlowPath flowPath : flowPaths) {
 	    //
 	    // Delete the flow entries from the switches
 	    //