BUG-2218: Keep existing link augmentations during discovery process
[controller.git] / opendaylight / adsal / forwardingrulesmanager / implementation / src / main / java / org / opendaylight / controller / forwardingrulesmanager / internal / FlowEntryDistributionOrderFutureTask.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 /**
10  * Class which will monitor the completion of a FlowEntryDistributionOrder it
11  * implements a Future interface so it can be inspected by who is waiting for
12  * it.
13  */
14 package org.opendaylight.controller.forwardingrulesmanager.internal;
15
16 import java.util.concurrent.CountDownLatch;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.Future;
19 import java.util.concurrent.TimeUnit;
20 import java.util.concurrent.TimeoutException;
21
22 import org.opendaylight.controller.forwardingrulesmanager.implementation.data.FlowEntryDistributionOrder;
23 import org.opendaylight.controller.sal.utils.Status;
24 import org.opendaylight.controller.sal.utils.StatusCode;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Class which will monitor the completion of a FlowEntryDistributionOrder it
30  * implements a Future interface so it can be inspected by who is waiting for
31  * it.
32  */
33 final class FlowEntryDistributionOrderFutureTask implements Future<Status> {
34     private final FlowEntryDistributionOrder order;
35     private boolean amICancelled;
36     private CountDownLatch waitingLatch;
37     private Status retStatus;
38     private static final Logger logger = LoggerFactory.getLogger(FlowEntryDistributionOrderFutureTask.class);
39     // Don't wait forever to program, rather timeout if there are issues, and
40     // log an error
41     private long timeout;
42     private static final Long DEFAULTTIMEOUT = 30000L;
43
44     /**
45      * @param order
46      *            for which we are monitoring the execution
47      */
48     FlowEntryDistributionOrderFutureTask(FlowEntryDistributionOrder order) {
49         // Order being monitored
50         this.order = order;
51         this.amICancelled = false;
52         // We need to wait for one completion to happen
53         this.waitingLatch = new CountDownLatch(1);
54         // No return status yet!
55         this.retStatus = new Status(StatusCode.UNDEFINED);
56         // Set the timeout
57         String strTimeout = System.getProperty("FlowEntryDistributionOrderFutureTask.timeout",
58                                                DEFAULTTIMEOUT.toString());
59         try {
60             timeout = Long.parseLong(strTimeout);
61         } catch (Exception e) {
62             timeout = DEFAULTTIMEOUT;
63         }
64     }
65
66     @Override
67     public boolean cancel(boolean mayInterruptIfRunning) {
68         if (this.waitingLatch.getCount() != 0L) {
69             this.retStatus = new Status(StatusCode.GONE);
70             this.waitingLatch.countDown();
71             logger.trace("Cancelled the workOrder");
72             return true;
73         }
74         return false;
75     }
76
77     @Override
78     public Status get() throws InterruptedException, ExecutionException {
79         boolean didFinish = false;
80         logger.trace("Getting status for order {}", this.order);
81         // If i'm done lets return the status as many times as caller wants
82         if (this.waitingLatch.getCount() == 0L) {
83             logger.trace("get returns the status without waiting");
84             return retStatus;
85         }
86
87         logger.trace("Start waiting for status to come back");
88         // Wait till someone signal that we are done
89         didFinish = this.waitingLatch.await(this.timeout, TimeUnit.MILLISECONDS);
90
91         if (didFinish) {
92             logger.trace("Waiting for the status of order {} is over, returning it", this.order);
93             // Return the known status
94             return retStatus;
95         } else {
96             logger.error("Timing out, the workStatus for order {} has not come back in time!, it's hashcode is {}",
97                     this.order, this.order.hashCode());
98             return new Status(StatusCode.TIMEOUT);
99         }
100     }
101
102     @Override
103     public Status get(long timeout, TimeUnit unit) throws InterruptedException,
104             ExecutionException, TimeoutException {
105         boolean didFinish = false;
106         logger.trace("Getting status for order {}", this.order);
107         // If i'm done lets return the status as many times as caller wants
108         if (this.waitingLatch.getCount() == 0L) {
109             logger.trace("get returns the status without waiting");
110             return retStatus;
111         }
112
113         logger.trace("Start waiting for status to come back");
114         // Wait till someone signal that we are done
115         didFinish = this.waitingLatch.await(timeout, unit);
116
117         if (didFinish) {
118             logger.trace("Waiting for the status is over, returning it");
119             // Return the known status, could also be null if didn't return
120             return retStatus;
121         } else {
122             // No need to bark here as long as this routine could indeed
123             // timeout
124             logger.trace("Timing out, the workStatus for order {} has not come back in time!", this.order);
125             return new Status(StatusCode.TIMEOUT);
126         }
127     }
128
129     @Override
130     public boolean isCancelled() {
131         return this.amICancelled;
132     }
133
134     @Override
135     public boolean isDone() {
136         return (this.waitingLatch.getCount() == 0L);
137     }
138
139     /**
140      * Used by the thread that gets back the status for the order so can unblock
141      * an eventual caller waiting on the result to comes back
142      *
143      * @param order
144      * @param retStatus
145      */
146     void gotStatus(FlowEntryDistributionOrder order, Status retStatus) {
147         logger.trace("Got status for order:{} \n Status:{}", order, retStatus);
148         if (!order.equals(this.order)) {
149             logger.error("Didn't get a result for an order we did issue order expected:{}, order received:{}",
150                     this.order, order);
151             // Weird we got a call for an order we didn't make
152             return;
153         }
154         this.retStatus = retStatus;
155         // Now we are not waiting any longer
156         this.waitingLatch.countDown();
157         logger.trace("Unlocked the Future");
158     }
159
160     /**
161      * Getter for the workOrder for which the order is waiting for
162      * @return the order
163      */
164     public FlowEntryDistributionOrder getOrder() {
165         return order;
166     }
167 }