Merge "Update devices page"
[controller.git] / opendaylight / forwardingrulesmanager / implementation / src / main / java / org / opendaylight / controller / forwardingrulesmanager / internal / FlowEntryDistributionOrderFutureTask.java
index 9761a433a848f2f4bc802fef2e47201c5170a2b5..b8c2d1db55067b9fc880ccfa74d352a0a45965a0 100644 (file)
@@ -22,6 +22,8 @@ import java.util.concurrent.TimeoutException;
 import org.opendaylight.controller.forwardingrulesmanager.implementation.data.FlowEntryDistributionOrder;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Class which will monitor the completion of a FlowEntryDistributionOrder it
@@ -33,6 +35,11 @@ final class FlowEntryDistributionOrderFutureTask implements Future<Status> {
     private boolean amICancelled;
     private CountDownLatch waitingLatch;
     private Status retStatus;
+    private static final Logger logger = LoggerFactory.getLogger(FlowEntryDistributionOrderFutureTask.class);
+    // Don't wait forever to program, rather timeout if there are issues, and
+    // log an error
+    private long timeout;
+    private static final Long DEFAULTTIMEOUT = 30000L;
 
     /**
      * @param order
@@ -46,40 +53,77 @@ final class FlowEntryDistributionOrderFutureTask implements Future<Status> {
         this.waitingLatch = new CountDownLatch(1);
         // No return status yet!
         this.retStatus = new Status(StatusCode.UNDEFINED);
+        // Set the timeout
+        String strTimeout = System.getProperty("FlowEntryDistributionOrderFutureTask.timeout",
+                                               DEFAULTTIMEOUT.toString());
+        try {
+            timeout = Long.parseLong(strTimeout);
+        } catch (Exception e) {
+            timeout = DEFAULTTIMEOUT;
+        }
     }
 
     @Override
     public boolean cancel(boolean mayInterruptIfRunning) {
+        if (this.waitingLatch.getCount() != 0L) {
+            this.retStatus = new Status(StatusCode.GONE);
+            this.waitingLatch.countDown();
+            logger.trace("Cancelled the workOrder");
+            return true;
+        }
         return false;
     }
 
     @Override
     public Status get() throws InterruptedException, ExecutionException {
+        boolean didFinish = false;
+        logger.trace("Getting status for order {}", this.order);
         // If i'm done lets return the status as many times as caller wants
         if (this.waitingLatch.getCount() == 0L) {
+            logger.trace("get returns the status without waiting");
             return retStatus;
         }
 
+        logger.trace("Start waiting for status to come back");
         // Wait till someone signal that we are done
-        this.waitingLatch.await();
+        didFinish = this.waitingLatch.await(this.timeout, TimeUnit.MILLISECONDS);
 
-        // Return the known status
-        return retStatus;
+        if (didFinish) {
+            logger.trace("Waiting for the status of order {} is over, returning it", this.order);
+            // Return the known status
+            return retStatus;
+        } else {
+            logger.error("Timing out, the workStatus for order {} has not come back in time!, it's hashcode is {}",
+                    this.order, this.order.hashCode());
+            return new Status(StatusCode.TIMEOUT);
+        }
     }
 
     @Override
     public Status get(long timeout, TimeUnit unit) throws InterruptedException,
             ExecutionException, TimeoutException {
+        boolean didFinish = false;
+        logger.trace("Getting status for order {}", this.order);
         // If i'm done lets return the status as many times as caller wants
         if (this.waitingLatch.getCount() == 0L) {
+            logger.trace("get returns the status without waiting");
             return retStatus;
         }
 
+        logger.trace("Start waiting for status to come back");
         // Wait till someone signal that we are done
-        this.waitingLatch.await(timeout, unit);
+        didFinish = this.waitingLatch.await(timeout, unit);
 
-        // Return the known status, could also be null if didn't return
-        return retStatus;
+        if (didFinish) {
+            logger.trace("Waiting for the status is over, returning it");
+            // Return the known status, could also be null if didn't return
+            return retStatus;
+        } else {
+            // No need to bark here as long as this routine could indeed
+            // timeout
+            logger.trace("Timing out, the workStatus for order {} has not come back in time!", this.order);
+            return new Status(StatusCode.TIMEOUT);
+        }
     }
 
     @Override
@@ -100,12 +144,24 @@ final class FlowEntryDistributionOrderFutureTask implements Future<Status> {
      * @param retStatus
      */
     void gotStatus(FlowEntryDistributionOrder order, Status retStatus) {
-        if (order != this.order) {
+        logger.trace("Got status for order:{} \n Status:{}", order, retStatus);
+        if (!order.equals(this.order)) {
+            logger.error("Didn't get a result for an order we did issue order expected:{}, order received:{}",
+                    this.order, order);
             // Weird we got a call for an order we didn't make
             return;
         }
         this.retStatus = retStatus;
         // Now we are not waiting any longer
         this.waitingLatch.countDown();
+        logger.trace("Unlocked the Future");
+    }
+
+    /**
+     * Getter for the workOrder for which the order is waiting for
+     * @return the order
+     */
+    public FlowEntryDistributionOrder getOrder() {
+        return order;
     }
 }