blob: d1c43c5fc8a785efb814d004519497ccc6cf869f [file] [log] [blame]
Sho SHIMIZU913969b2014-08-18 15:04:21 -07001package net.onrc.onos.core.newintent;
2
Brian O'Connorab3e9e62014-09-09 23:45:55 -07003import static com.google.common.base.Preconditions.checkNotNull;
4import static net.onrc.onos.api.flowmanager.FlowState.FAILED;
5import static net.onrc.onos.api.flowmanager.FlowState.INSTALLED;
6import static net.onrc.onos.api.flowmanager.FlowState.WITHDRAWN;
7
8import java.util.concurrent.CountDownLatch;
9
Sho SHIMIZU913969b2014-08-18 15:04:21 -070010import net.onrc.onos.api.flowmanager.Flow;
11import net.onrc.onos.api.flowmanager.FlowBatchHandle;
12import net.onrc.onos.api.flowmanager.FlowBatchStateChangedEvent;
13import net.onrc.onos.api.flowmanager.FlowId;
14import net.onrc.onos.api.flowmanager.FlowManagerListener;
15import net.onrc.onos.api.flowmanager.FlowManagerService;
16import net.onrc.onos.api.flowmanager.FlowState;
17import net.onrc.onos.api.flowmanager.FlowStateChange;
18import net.onrc.onos.api.flowmanager.FlowStatesChangedEvent;
19import net.onrc.onos.api.newintent.InstallableIntent;
20import net.onrc.onos.api.newintent.Intent;
21import net.onrc.onos.api.newintent.IntentInstaller;
22
Brian O'Connorab3e9e62014-09-09 23:45:55 -070023import com.google.common.base.Optional;
24import com.google.common.base.Predicate;
25import com.google.common.collect.Iterables;
Sho SHIMIZU913969b2014-08-18 15:04:21 -070026
27// TODO: consider naming because to call Flow manager's API will be removed
28// in long-term refactoring
Sho SHIMIZU913969b2014-08-18 15:04:21 -070029/**
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
Brian O'Connorab3e9e62014-09-09 23:45:55 -070057 // TODO (BOC) this blocks a Hazelcast thread, commenting out for now
58 // try {
59 // listener.await();
60 // if (listener.getFinalState() == FAILED) {
61 // throw new IntentInstallationException("intent installation failed: "
62 // + intent);
63 // }
64 // } catch (InterruptedException e) {
65 // throw new IntentInstallationException("intent installation failed: "
66 // + intent, e);
67 // } finally {
68 // flowManager.removeListener(listener);
69 // }
Sho SHIMIZU913969b2014-08-18 15:04:21 -070070 }
71
72 protected void removeFlow(Intent intent, Flow flow) {
73 RemovalListener listener = new RemovalListener(flow.getId());
74 flowManager.addListener(listener);
75
76 FlowBatchHandle handle = flowManager.removeFlow(flow.getId());
77 if (handle == null) {
78 throw new IntentRemovalException("intent removal failed: " + intent);
79 }
80
81
82 try {
83 listener.await();
84 if (listener.getFinalState() == FAILED) {
85 throw new IntentInstallationException("intent removal failed: " + intent);
86 }
87 } catch (InterruptedException e) {
88 throw new IntentInstallationException("intent removal failed: " + intent, e);
89 } finally {
90 flowManager.removeListener(listener);
91 }
92 }
93
94 protected abstract static class SyncListener implements FlowManagerListener {
95 protected final FlowId target;
96 protected final CountDownLatch latch = new CountDownLatch(1);
97 protected FlowState finalState;
98
99 protected SyncListener(FlowId target) {
100 this.target = checkNotNull(target);
101 }
102
103 protected Optional<FlowStateChange> findTargetFlow(FlowStatesChangedEvent event) {
104 return Iterables.tryFind(event.getStateChanges(), new Predicate<FlowStateChange>() {
105 @Override
106 public boolean apply(FlowStateChange stateChange) {
107 return stateChange.getFlowId().equals(target);
108 }
109 });
110 }
111
112 public FlowState getFinalState() {
113 return finalState;
114 }
115
116 public void await() throws InterruptedException {
117 latch.await();
118 }
119 }
120
121 protected static class InstallationListener extends SyncListener {
122 public InstallationListener(FlowId target) {
123 super(target);
124 }
125
126 @Override
127 public void flowStatesChanged(FlowStatesChangedEvent event) {
128 Optional<FlowStateChange> optional = findTargetFlow(event);
129
130 if (!optional.isPresent()) {
131 return;
132 }
133
134 FlowStateChange stateChange = optional.get();
135 switch (stateChange.getCurrentState()) {
136 case INSTALLED:
137 latch.countDown();
138 finalState = INSTALLED;
139 break;
140 case FAILED:
141 latch.countDown();
142 finalState = FAILED;
143 break;
144 default:
145 break;
146 }
147 }
148
149 @Override
150 public void flowBatchStateChanged(FlowBatchStateChangedEvent event) {
151 // nop
152 }
153 }
154
155 protected static class RemovalListener extends SyncListener {
156 public RemovalListener(FlowId target) {
157 super(target);
158 }
159
160 @Override
161 public void flowStatesChanged(FlowStatesChangedEvent event) {
162 Optional<FlowStateChange> optional = findTargetFlow(event);
163
164 if (!optional.isPresent()) {
165 return;
166 }
167
168 FlowStateChange stateChange = optional.get();
169 switch (stateChange.getCurrentState()) {
170 case WITHDRAWN:
171 latch.countDown();
172 finalState = WITHDRAWN;
173 break;
174 case FAILED:
175 latch.countDown();
176 finalState = FAILED;
177 break;
178 default:
179 break;
180 }
181 }
182
183 @Override
184 public void flowBatchStateChanged(FlowBatchStateChangedEvent event) {
185 // nop
186 }
187 }
188}