blob: 9d21771555fc1a6a755a7c202db8126cb5fb2066 [file] [log] [blame]
Sho SHIMIZU913969b2014-08-18 15:04:21 -07001package net.onrc.onos.core.newintent;
2
3import com.google.common.base.Optional;
4import com.google.common.base.Predicate;
5import com.google.common.collect.Iterables;
6import net.onrc.onos.api.flowmanager.Flow;
7import net.onrc.onos.api.flowmanager.FlowBatchHandle;
8import net.onrc.onos.api.flowmanager.FlowBatchStateChangedEvent;
9import net.onrc.onos.api.flowmanager.FlowId;
10import net.onrc.onos.api.flowmanager.FlowManagerListener;
11import net.onrc.onos.api.flowmanager.FlowManagerService;
12import net.onrc.onos.api.flowmanager.FlowState;
13import net.onrc.onos.api.flowmanager.FlowStateChange;
14import net.onrc.onos.api.flowmanager.FlowStatesChangedEvent;
15import net.onrc.onos.api.newintent.InstallableIntent;
16import net.onrc.onos.api.newintent.Intent;
17import net.onrc.onos.api.newintent.IntentInstaller;
18
19import java.util.concurrent.CountDownLatch;
20
21import static com.google.common.base.Preconditions.checkNotNull;
22import static net.onrc.onos.api.flowmanager.FlowState.FAILED;
23import static net.onrc.onos.api.flowmanager.FlowState.INSTALLED;
24import static net.onrc.onos.api.flowmanager.FlowState.WITHDRAWN;
25
26// TODO: consider naming because to call Flow manager's API will be removed
27// in long-term refactoring
28// TODO: consider unifying the install() and remove() by pulling up to this class
29/**
30 * Base class for implementing an intent installer, which use Flow Manager's API.
31 *
32 * @param <T> the type of intent
33 */
34public abstract class AbstractIntentInstaller<T extends InstallableIntent>
35 implements IntentInstaller<T> {
36 protected final FlowManagerService flowManager;
37
38 /**
39 * Constructs a base class with the specified Flow Manager service.
40 *
41 * @param flowManager Flow manager service, which is used to install/remove
42 * an intent
43 */
44 protected AbstractIntentInstaller(FlowManagerService flowManager) {
45 this.flowManager = flowManager;
46 }
47
48 protected void installFlow(Intent intent, Flow flow) {
49 InstallationListener listener = new InstallationListener(flow.getId());
50 flowManager.addListener(listener);
51
52 FlowBatchHandle handle = flowManager.addFlow(flow);
53 if (handle == null) {
54 throw new IntentInstallationException("intent installation failed: " + intent);
55 }
56
57 try {
58 listener.await();
59 if (listener.getFinalState() == FAILED) {
60 throw new IntentInstallationException("intent installation failed: " + intent);
61 }
62 } catch (InterruptedException e) {
63 throw new IntentInstallationException("intent installation failed: " + intent, e);
64 } finally {
65 flowManager.removeListener(listener);
66 }
67 }
68
69 protected void removeFlow(Intent intent, Flow flow) {
70 RemovalListener listener = new RemovalListener(flow.getId());
71 flowManager.addListener(listener);
72
73 FlowBatchHandle handle = flowManager.removeFlow(flow.getId());
74 if (handle == null) {
75 throw new IntentRemovalException("intent removal failed: " + intent);
76 }
77
78
79 try {
80 listener.await();
81 if (listener.getFinalState() == FAILED) {
82 throw new IntentInstallationException("intent removal failed: " + intent);
83 }
84 } catch (InterruptedException e) {
85 throw new IntentInstallationException("intent removal failed: " + intent, e);
86 } finally {
87 flowManager.removeListener(listener);
88 }
89 }
90
91 protected abstract static class SyncListener implements FlowManagerListener {
92 protected final FlowId target;
93 protected final CountDownLatch latch = new CountDownLatch(1);
94 protected FlowState finalState;
95
96 protected SyncListener(FlowId target) {
97 this.target = checkNotNull(target);
98 }
99
100 protected Optional<FlowStateChange> findTargetFlow(FlowStatesChangedEvent event) {
101 return Iterables.tryFind(event.getStateChanges(), new Predicate<FlowStateChange>() {
102 @Override
103 public boolean apply(FlowStateChange stateChange) {
104 return stateChange.getFlowId().equals(target);
105 }
106 });
107 }
108
109 public FlowState getFinalState() {
110 return finalState;
111 }
112
113 public void await() throws InterruptedException {
114 latch.await();
115 }
116 }
117
118 protected static class InstallationListener extends SyncListener {
119 public InstallationListener(FlowId target) {
120 super(target);
121 }
122
123 @Override
124 public void flowStatesChanged(FlowStatesChangedEvent event) {
125 Optional<FlowStateChange> optional = findTargetFlow(event);
126
127 if (!optional.isPresent()) {
128 return;
129 }
130
131 FlowStateChange stateChange = optional.get();
132 switch (stateChange.getCurrentState()) {
133 case INSTALLED:
134 latch.countDown();
135 finalState = INSTALLED;
136 break;
137 case FAILED:
138 latch.countDown();
139 finalState = FAILED;
140 break;
141 default:
142 break;
143 }
144 }
145
146 @Override
147 public void flowBatchStateChanged(FlowBatchStateChangedEvent event) {
148 // nop
149 }
150 }
151
152 protected static class RemovalListener extends SyncListener {
153 public RemovalListener(FlowId target) {
154 super(target);
155 }
156
157 @Override
158 public void flowStatesChanged(FlowStatesChangedEvent event) {
159 Optional<FlowStateChange> optional = findTargetFlow(event);
160
161 if (!optional.isPresent()) {
162 return;
163 }
164
165 FlowStateChange stateChange = optional.get();
166 switch (stateChange.getCurrentState()) {
167 case WITHDRAWN:
168 latch.countDown();
169 finalState = WITHDRAWN;
170 break;
171 case FAILED:
172 latch.countDown();
173 finalState = FAILED;
174 break;
175 default:
176 break;
177 }
178 }
179
180 @Override
181 public void flowBatchStateChanged(FlowBatchStateChangedEvent event) {
182 // nop
183 }
184 }
185}