Merge branch 'ONOS-ONRC2014-Measurements' of https://github.com/OPENNETWORKINGLAB/ONOS into topodev

Conflicts:
	src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
index 0728f9a..4c801d6 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
@@ -14,6 +14,7 @@
 
 import net.floodlightcontroller.core.IOFSwitch;
 import net.onrc.onos.datagrid.IDatagridService;
+import net.onrc.onos.graph.GraphDBOperation;
 import net.onrc.onos.ofcontroller.topology.Topology;
 import net.onrc.onos.ofcontroller.topology.TopologyElement;
 import net.onrc.onos.ofcontroller.topology.TopologyManager;
@@ -46,7 +47,11 @@
 class FlowEventHandler extends Thread implements IFlowEventHandlerService {
     /** The logger. */
     private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
+    
+    // Flag to enable feature of acquiring topology information from DB instead of datagrid.
+    private final boolean accessDBFlag = false;
 
+    private GraphDBOperation dbHandler;
     private FlowManager flowManager;		// The Flow Manager to use
     private IDatagridService datagridService;	// The Datagrid Service to use
     private Topology topology;			// The network topology
@@ -93,10 +98,12 @@
      * @param datagridService the Datagrid Service to use.
      */
     FlowEventHandler(FlowManager flowManager,
-		     IDatagridService datagridService) {
+		     IDatagridService datagridService,
+		     GraphDBOperation dbHandler) {
 	this.flowManager = flowManager;
 	this.datagridService = datagridService;
 	this.topology = new Topology();
+	this.dbHandler = dbHandler;
     }
 
     /**
@@ -185,6 +192,7 @@
 		    if (event.eventData() instanceof TopologyElement) {
 			EventEntry<TopologyElement> topologyEventEntry =
 			    (EventEntry<TopologyElement>)event;
+			
 			topologyEvents.add(topologyEventEntry);
 			continue;
 		    }
@@ -224,7 +232,7 @@
 	    log.debug("Exception processing Network Events: ", exception);
 	}
     }
-
+    
     /**
      * Process the events (if any)
      */
@@ -493,20 +501,28 @@
 	// Process all Topology events and update the appropriate state
 	//
 	boolean isTopologyModified = false;
-	for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
-	    TopologyElement topologyElement = eventEntry.eventData();
+	if (accessDBFlag) {
+		log.debug("[BEFORE] {}", topology.toString());
+		if (! topology.readFromDatabase(dbHandler)) {
+			isTopologyModified = true;
+		}
+		log.debug("[AFTER] {}", topology.toString());
+	} else {
+		for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
+		    TopologyElement topologyElement = eventEntry.eventData();
+			
+		    log.debug("Topology Event: {} {}", eventEntry.eventType(),
+				      topologyElement.toString());
 
-	    log.debug("Topology Event: {} {}", eventEntry.eventType(),
-		      topologyElement);
-
-	    switch (eventEntry.eventType()) {
-	    case ENTRY_ADD:
-		isTopologyModified |= topology.addTopologyElement(topologyElement);
-		break;
-	    case ENTRY_REMOVE:
-		isTopologyModified |= topology.removeTopologyElement(topologyElement);
-		break;
-	    }
+		    switch (eventEntry.eventType()) {
+		    case ENTRY_ADD:
+			isTopologyModified |= topology.addTopologyElement(topologyElement);
+			break;
+		    case ENTRY_REMOVE:
+			isTopologyModified |= topology.removeTopologyElement(topologyElement);
+			break;
+		    }
+		}
 	}
 	if (isTopologyModified) {
 	    // TODO: For now, if the topology changes, we recompute all Flows
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 02e3210..388035a 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -224,7 +224,7 @@
 	//  - register with the Datagrid Service
 	//  - startup
 	//
-	flowEventHandler = new FlowEventHandler(this, datagridService);
+	flowEventHandler = new FlowEventHandler(this, datagridService, dbHandlerInner);
 	datagridService.registerFlowEventHandlerService(flowEventHandler);
 	flowEventHandler.start();
     }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
index fc75591..dedb589 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
@@ -381,12 +381,18 @@
      * Read topology state from the database.
      *
      * @param dbHandler the Graph Database handler to use.
+     * @return true if topology is updated. In other words,
+     * 		topology read from database is different from current topology.
      */
-    public void readFromDatabase(GraphDBOperation dbHandler) {
+    public boolean readFromDatabase(GraphDBOperation dbHandler) {
 	//
 	// Fetch the relevant info from the Switch and Port vertices
 	// from the Titan Graph.
 	//
+    
+	Map<Long,Node> oldNodesMap = nodesMap;
+	nodesMap = new TreeMap<Long,Node>();
+	
 	Iterable<ISwitchObject> activeSwitches = dbHandler.getActiveSwitches();
 	for (ISwitchObject switchObj : activeSwitches) {
 	    Vertex nodeVertex = switchObj.asVertex();
@@ -450,5 +456,76 @@
 	    }
 	}
 	dbHandler.commit();
+	return ! compareTopology(oldNodesMap, nodesMap);
+    }
+    
+    // TODO Merge into loops in readFromDatabase() can reduce execution time.
+    /**
+     * Check given two topology are identical or not.
+     * @param topo1
+     * @param topo2
+     * @return true if identical
+     */
+    private boolean compareTopology(Map<Long,Node> topo1, Map<Long,Node> topo2) {
+    	if (topo1.size() != topo2.size()) {
+    		return false;
+    	}
+    	
+    	for (Map.Entry<Long,Node> nodeEntry : topo1.entrySet()) {
+    		Long dpid = nodeEntry.getKey();
+    		if (! topo2.containsKey(dpid)) {
+    			return false;
+    		}
+    		
+    		Node n1 = nodeEntry.getValue();
+    		Node n2 = topo2.get(dpid);
+    		
+    		// check port identity
+    		if (n1.ports().size() != n2.ports().size()) {
+    			return false;
+    		}
+    		for (Integer port : n1.ports().keySet()) {
+    			if (! n2.ports().containsKey(port)) {
+    				return false;
+    			}
+    		}
+    		
+    		// check link identity
+    		if (n1.links.size() != n2.links.size()) {
+    			return false;
+    		}
+    		for (Map.Entry<Integer, Node.Link> linkEntry : n1.links.entrySet()) {
+    			Integer p1 = linkEntry.getKey();
+    			Node.Link l1 = linkEntry.getValue();
+    			
+    			if (! n2.links.containsKey(p1)) {
+    				return false;
+    			}
+    			Node.Link l2 = n2.links.get(p1);
+    			
+    		   	// Supposition: Link's "me" and "neighbor" is properly set.
+    			if (l1.myPort != l2.myPort ||
+    				l1.neighborPort != l2.neighborPort) {
+    				return false;
+    			}
+    		}
+    	}
+    	return true;
+    }
+    
+    // Only for debug use
+    @Override
+    public String toString() {
+    	long numNodes = nodesMap.size();
+    	long numLinks = 0;
+    	for (Map.Entry<Long, Node> entry : nodesMap.entrySet()) {
+    		Node n = entry.getValue();
+    		for (Map.Entry<Integer, Node.Link> linkEntry : n.links.entrySet()) {
+    			if (n.nodeId > linkEntry.getValue().neighbor.nodeId) {
+    				++numLinks;
+    			}
+    		}
+    	}
+    	return "Topology has " + numNodes + " Nodes and " + numLinks + " Links.";
     }
 }