Add backend support for collecting the time it takes to
install each Flow.

The new REST call is "wm/flow/measurement-get-per-flow-install-time/json"
The result is returned in a multi-line string with the following format
per line:

  ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 1020eab..8aec20f 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -99,6 +99,7 @@
     private long measurementStartTimeProcessingPaths = 0;
     private long measurementEndTimeProcessingPaths = 0;
     Map<Long, ?> measurementShortestPathTopo = null;
+    private String measurementPerFlowStr = new String();
 
     /** The logger. */
     private static Logger log = LoggerFactory.getLogger(FlowManager.class);
@@ -815,7 +816,7 @@
 	    thread.start();
 	}
 
-	// Want for all threads to complete
+	// Wait for all threads to complete
 	for (Thread thread : threads) {
 	    try {
 		thread.join();
@@ -1960,12 +1961,39 @@
      */
     @Override
     public boolean measurementInstallPaths(Integer numThreads) {
-	List<Thread> threads = new LinkedList<Thread>();
-
 	// Create a copy of the Flow Paths to install
 	final ConcurrentLinkedQueue<FlowPath> measurementProcessingPaths =
 	    new ConcurrentLinkedQueue<FlowPath>(measurementStoredPaths);
 
+	/**
+	 * A Thread-wrapper class for executing the threads and collecting
+	 * the measurement data.
+	 */
+	class MyThread extends Thread {
+	    public long[] execTime = new long[2000];
+	    public int samples = 0;
+	    public int threadId = -1;
+	    @Override
+	    public void run() {
+		while (true) {
+		    FlowPath flowPath = measurementProcessingPaths.poll();
+		    if (flowPath == null)
+			return;
+		    // Install the Flow Path
+		    FlowId flowId = new FlowId();
+		    String dataPathSummaryStr =
+			flowPath.dataPath().dataPathSummary();
+		    long startTime = System.nanoTime();
+		    addFlow(flowPath, flowId, dataPathSummaryStr);
+		    long endTime = System.nanoTime();
+		    execTime[samples] = endTime - startTime;
+		    samples++;
+		}
+	    }
+	};
+
+	List<MyThread> threads = new LinkedList<MyThread>();
+
 	log.debug("Measurement Installing {} flows",
 		  measurementProcessingPaths.size());
 
@@ -1973,20 +2001,8 @@
 	// Create the threads to install the Flow Paths
 	//
 	for (int i = 0; i < numThreads; i++) {
-	    Thread thread = new Thread(new Runnable() {
-		@Override
-		public void run() {
-		    while (true) {
-			FlowPath flowPath = measurementProcessingPaths.poll();
-			if (flowPath == null)
-			    return;
-			// Install the Flow Path
-			FlowId flowId = new FlowId();
-			String dataPathSummaryStr =
-			    flowPath.dataPath().dataPathSummary();
-			addFlow(flowPath, flowId, dataPathSummaryStr);
-		    }
-		}}, "Measurement Add Flow Path");
+	    MyThread thread = new MyThread();
+	    thread.threadId = i;
 	    threads.add(thread);
 	}
 
@@ -1999,7 +2015,7 @@
 	    thread.start();
 	}
 
-	// Want for all threads to complete
+	// Wait for all threads to complete
 	for (Thread thread : threads) {
 	    try {
 		thread.join();
@@ -2011,6 +2027,20 @@
 	// Record the end of processing
 	measurementEndTimeProcessingPaths = System.nanoTime();
 
+	//
+	// Prepare the string with measurement data per each Flow Path
+	// installation.
+	// The string is multiple lines: one line per Flow Path installation:
+	//    ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+	//
+	measurementPerFlowStr = new String();
+	String eol = System.getProperty("line.separator");
+	for (MyThread thread : threads) {
+	    for (int i = 0; i < thread.samples; i++) {
+		measurementPerFlowStr += "ThreadAndTimePerFlow " + thread.threadId + " " + numThreads + " " + thread.execTime[i] + eol;
+	    }
+	}
+
 	return true;
     }
 
@@ -2027,6 +2057,17 @@
     }
 
     /**
+     * Get the measurement install time per Flow.
+     *
+     * @return a multi-line string with the following format per line:
+     * ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+     */
+    @Override
+    public String measurementGetPerFlowInstallTime() {
+	return new String(measurementPerFlowStr);
+    }
+
+    /**
      * Clear the path flows stored for measurement purpose.
      *
      * @return true on success, otherwise false.
@@ -2037,6 +2078,7 @@
 	topoRouteService.dropShortestPathTopo(measurementShortestPathTopo);
 	measurementStartTimeProcessingPaths = 0;
 	measurementEndTimeProcessingPaths = 0;
+	measurementPerFlowStr = new String();
 
 	return true;
     }