/* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ /** * Class which will monitor the completion of a FlowEntryDistributionOrder it * implements a Future interface so it can be inspected by who is waiting for * it. */ package org.opendaylight.controller.forwardingrulesmanager.internal; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; 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 * implements a Future interface so it can be inspected by who is waiting for * it. */ final class FlowEntryDistributionOrderFutureTask implements Future { private final FlowEntryDistributionOrder order; private boolean amICancelled; private CountDownLatch waitingLatch; private Status retStatus; private static final Logger logger = LoggerFactory.getLogger(FlowEntryDistributionOrderFutureTask.class); /** * @param order * for which we are monitoring the execution */ FlowEntryDistributionOrderFutureTask(FlowEntryDistributionOrder order) { // Order being monitored this.order = order; this.amICancelled = false; // We need to wait for one completion to happen this.waitingLatch = new CountDownLatch(1); // No return status yet! this.retStatus = new Status(StatusCode.UNDEFINED); } @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; } @Override public Status get() throws InterruptedException, ExecutionException { 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(); logger.trace("Waiting for the status is over, returning it"); // Return the known status return retStatus; } @Override public Status get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 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); logger.trace("Waiting for the status is over, returning it"); // Return the known status, could also be null if didn't return return retStatus; } @Override public boolean isCancelled() { return this.amICancelled; } @Override public boolean isDone() { return (this.waitingLatch.getCount() == 0L); } /** * Used by the thread that gets back the status for the order so can unblock * an eventual caller waiting on the result to comes back * * @param order * @param retStatus */ void gotStatus(FlowEntryDistributionOrder order, Status retStatus) { 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"); } }