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