| package net.onrc.onos.core.newintent; |
| |
| import com.google.common.base.Optional; |
| import com.google.common.base.Predicate; |
| import com.google.common.collect.Iterables; |
| import net.onrc.onos.api.flowmanager.Flow; |
| import net.onrc.onos.api.flowmanager.FlowBatchHandle; |
| import net.onrc.onos.api.flowmanager.FlowBatchStateChangedEvent; |
| import net.onrc.onos.api.flowmanager.FlowId; |
| import net.onrc.onos.api.flowmanager.FlowManagerListener; |
| import net.onrc.onos.api.flowmanager.FlowManagerService; |
| import net.onrc.onos.api.flowmanager.FlowState; |
| import net.onrc.onos.api.flowmanager.FlowStateChange; |
| import net.onrc.onos.api.flowmanager.FlowStatesChangedEvent; |
| import net.onrc.onos.api.newintent.InstallableIntent; |
| import net.onrc.onos.api.newintent.Intent; |
| import net.onrc.onos.api.newintent.IntentInstaller; |
| |
| import java.util.concurrent.CountDownLatch; |
| |
| import static com.google.common.base.Preconditions.checkNotNull; |
| import static net.onrc.onos.api.flowmanager.FlowState.FAILED; |
| import static net.onrc.onos.api.flowmanager.FlowState.INSTALLED; |
| import static net.onrc.onos.api.flowmanager.FlowState.WITHDRAWN; |
| |
| // TODO: consider naming because to call Flow manager's API will be removed |
| // in long-term refactoring |
| // TODO: consider unifying the install() and remove() by pulling up to this class |
| /** |
| * Base class for implementing an intent installer, which use Flow Manager's API. |
| * |
| * @param <T> the type of intent |
| */ |
| public abstract class AbstractIntentInstaller<T extends InstallableIntent> |
| implements IntentInstaller<T> { |
| protected final FlowManagerService flowManager; |
| |
| /** |
| * Constructs a base class with the specified Flow Manager service. |
| * |
| * @param flowManager Flow manager service, which is used to install/remove |
| * an intent |
| */ |
| protected AbstractIntentInstaller(FlowManagerService flowManager) { |
| this.flowManager = flowManager; |
| } |
| |
| protected void installFlow(Intent intent, Flow flow) { |
| InstallationListener listener = new InstallationListener(flow.getId()); |
| flowManager.addListener(listener); |
| |
| FlowBatchHandle handle = flowManager.addFlow(flow); |
| if (handle == null) { |
| throw new IntentInstallationException("intent installation failed: " + intent); |
| } |
| |
| try { |
| listener.await(); |
| if (listener.getFinalState() == FAILED) { |
| throw new IntentInstallationException("intent installation failed: " + intent); |
| } |
| } catch (InterruptedException e) { |
| throw new IntentInstallationException("intent installation failed: " + intent, e); |
| } finally { |
| flowManager.removeListener(listener); |
| } |
| } |
| |
| protected void removeFlow(Intent intent, Flow flow) { |
| RemovalListener listener = new RemovalListener(flow.getId()); |
| flowManager.addListener(listener); |
| |
| FlowBatchHandle handle = flowManager.removeFlow(flow.getId()); |
| if (handle == null) { |
| throw new IntentRemovalException("intent removal failed: " + intent); |
| } |
| |
| |
| try { |
| listener.await(); |
| if (listener.getFinalState() == FAILED) { |
| throw new IntentInstallationException("intent removal failed: " + intent); |
| } |
| } catch (InterruptedException e) { |
| throw new IntentInstallationException("intent removal failed: " + intent, e); |
| } finally { |
| flowManager.removeListener(listener); |
| } |
| } |
| |
| protected abstract static class SyncListener implements FlowManagerListener { |
| protected final FlowId target; |
| protected final CountDownLatch latch = new CountDownLatch(1); |
| protected FlowState finalState; |
| |
| protected SyncListener(FlowId target) { |
| this.target = checkNotNull(target); |
| } |
| |
| protected Optional<FlowStateChange> findTargetFlow(FlowStatesChangedEvent event) { |
| return Iterables.tryFind(event.getStateChanges(), new Predicate<FlowStateChange>() { |
| @Override |
| public boolean apply(FlowStateChange stateChange) { |
| return stateChange.getFlowId().equals(target); |
| } |
| }); |
| } |
| |
| public FlowState getFinalState() { |
| return finalState; |
| } |
| |
| public void await() throws InterruptedException { |
| latch.await(); |
| } |
| } |
| |
| protected static class InstallationListener extends SyncListener { |
| public InstallationListener(FlowId target) { |
| super(target); |
| } |
| |
| @Override |
| public void flowStatesChanged(FlowStatesChangedEvent event) { |
| Optional<FlowStateChange> optional = findTargetFlow(event); |
| |
| if (!optional.isPresent()) { |
| return; |
| } |
| |
| FlowStateChange stateChange = optional.get(); |
| switch (stateChange.getCurrentState()) { |
| case INSTALLED: |
| latch.countDown(); |
| finalState = INSTALLED; |
| break; |
| case FAILED: |
| latch.countDown(); |
| finalState = FAILED; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| @Override |
| public void flowBatchStateChanged(FlowBatchStateChangedEvent event) { |
| // nop |
| } |
| } |
| |
| protected static class RemovalListener extends SyncListener { |
| public RemovalListener(FlowId target) { |
| super(target); |
| } |
| |
| @Override |
| public void flowStatesChanged(FlowStatesChangedEvent event) { |
| Optional<FlowStateChange> optional = findTargetFlow(event); |
| |
| if (!optional.isPresent()) { |
| return; |
| } |
| |
| FlowStateChange stateChange = optional.get(); |
| switch (stateChange.getCurrentState()) { |
| case WITHDRAWN: |
| latch.countDown(); |
| finalState = WITHDRAWN; |
| break; |
| case FAILED: |
| latch.countDown(); |
| finalState = FAILED; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| @Override |
| public void flowBatchStateChanged(FlowBatchStateChangedEvent event) { |
| // nop |
| } |
| } |
| } |