blob: 387ef282d9152a50ab9acd8434a2124cd3a8c3f2 [file] [log] [blame]
Ray Milkey18b44ac2014-08-22 08:29:47 -07001package net.onrc.onos.core.matchaction;
2
Ray Milkey18b44ac2014-08-22 08:29:47 -07003import java.util.ArrayList;
Ray Milkey18b44ac2014-08-22 08:29:47 -07004import java.util.EventListener;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.List;
8import java.util.Map;
9import java.util.Set;
10import java.util.concurrent.ArrayBlockingQueue;
11import java.util.concurrent.BlockingQueue;
12import java.util.concurrent.ConcurrentHashMap;
13import java.util.concurrent.ConcurrentMap;
14import java.util.concurrent.ExecutionException;
15
Brian O'Connoraa5a7b92014-08-29 14:45:18 -070016import net.floodlightcontroller.core.IFloodlightProviderService;
17import net.floodlightcontroller.core.internal.OFMessageFuture;
18import net.floodlightcontroller.core.module.IFloodlightService;
19import net.onrc.onos.api.flowmanager.ConflictDetectionPolicy;
20import net.onrc.onos.core.datagrid.IDatagridService;
21import net.onrc.onos.core.datagrid.IEventChannel;
22import net.onrc.onos.core.datagrid.IEventChannelListener;
23import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Ray Milkey626a2b12014-09-02 11:19:06 -070024import net.onrc.onos.core.registry.IControllerRegistryService;
Brian O'Connoraa5a7b92014-08-29 14:45:18 -070025import net.onrc.onos.core.util.Dpid;
Ray Milkey626a2b12014-09-02 11:19:06 -070026import net.onrc.onos.core.util.IdBlockAllocator;
Brian O'Connoraa5a7b92014-08-29 14:45:18 -070027import net.onrc.onos.core.util.IdGenerator;
28import net.onrc.onos.core.util.SwitchPort;
29
30import org.apache.commons.lang3.tuple.Pair;
31import org.projectfloodlight.openflow.protocol.OFBarrierReply;
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
Ray Milkey18b44ac2014-08-22 08:29:47 -070034
Ray Milkey18b44ac2014-08-22 08:29:47 -070035/**
36 * Manages Match-Action entries.
37 * <p>
38 * TODO: Make all methods thread-safe
39 */
40public class MatchActionComponent implements MatchActionService, IFloodlightService {
41
42 private static final Logger log = LoggerFactory.getLogger(MatchActionService.class);
Ray Milkeya313cde2014-09-05 09:02:52 -070043 private final IFlowPusherService pusher;
44 private final IFloodlightProviderService provider;
Ray Milkey18b44ac2014-08-22 08:29:47 -070045
Ray Milkeya313cde2014-09-05 09:02:52 -070046 private final ConcurrentMap<MatchActionId, MatchAction> matchActionMap = new ConcurrentHashMap<>();
47 private final ConcurrentMap<MatchActionOperationsId, MatchActionOperations> matchSetMap =
Ray Milkey18b44ac2014-08-22 08:29:47 -070048 new ConcurrentHashMap<>();
49 // TODO - want something better here for the resolved Queue
Ray Milkeya313cde2014-09-05 09:02:52 -070050 private final BlockingQueue<MatchActionOperationsId> resolvedQueue = new ArrayBlockingQueue<>(100);
51 private final BlockingQueue<MatchActionOperations> installationWorkQueue = new ArrayBlockingQueue<>(100);
Ray Milkey18b44ac2014-08-22 08:29:47 -070052
Brian O'Connorab3e9e62014-09-09 23:45:55 -070053 private IEventChannel<Long, MatchActionOperations> installSetChannel;
Ray Milkey18b44ac2014-08-22 08:29:47 -070054 private IEventChannel<String, SwitchResultList> installSetReplyChannel;
55
Ray Milkey18b44ac2014-08-22 08:29:47 -070056 private final IDatagridService datagrid;
Ray Milkeya313cde2014-09-05 09:02:52 -070057 private final IControllerRegistryService registryService;
Ray Milkey626a2b12014-09-02 11:19:06 -070058
59 private MatchActionIdGeneratorWithIdBlockAllocator matchActionIdGenerator;
60 private MatchActionOperationsIdGeneratorWithIdBlockAllocator matchActionOperationsIdGenerator;
Ray Milkey18b44ac2014-08-22 08:29:47 -070061
Ray Milkeya313cde2014-09-05 09:02:52 -070062 /**
63 * Constructs a MatchActionComponent given the services it depends on.
64 *
65 * @param newDatagrid datagrid dependency
66 * @param newPusher flow pusher dependency
67 * @param newProvider provider used for switch queries
68 * @param newRegistryService registry for ID block allocation
69 */
Ray Milkey18b44ac2014-08-22 08:29:47 -070070 public MatchActionComponent(final IDatagridService newDatagrid,
71 final IFlowPusherService newPusher,
Ray Milkey626a2b12014-09-02 11:19:06 -070072 final IFloodlightProviderService newProvider,
73 final IControllerRegistryService newRegistryService) {
Ray Milkey18b44ac2014-08-22 08:29:47 -070074 datagrid = newDatagrid;
75 pusher = newPusher;
76 provider = newProvider;
Ray Milkey626a2b12014-09-02 11:19:06 -070077 registryService = newRegistryService;
Ray Milkey18b44ac2014-08-22 08:29:47 -070078 }
79
Ray Milkeya313cde2014-09-05 09:02:52 -070080 /**
81 * Starts the component. Created channels used for communication and
82 * creates producer and consumer threads.
83 */
Ray Milkey18b44ac2014-08-22 08:29:47 -070084 public void start() {
Ray Milkey626a2b12014-09-02 11:19:06 -070085 IdBlockAllocator idBlockAllocator = registryService;
86 matchActionIdGenerator =
87 new MatchActionIdGeneratorWithIdBlockAllocator(idBlockAllocator);
88 matchActionOperationsIdGenerator =
89 new MatchActionOperationsIdGeneratorWithIdBlockAllocator(idBlockAllocator);
90
Brian O'Connorab3e9e62014-09-09 23:45:55 -070091 final Installer installerListener = new Installer();
92 installSetChannel = datagrid.addListener(
93 "onos.matchaction.installSetChannel",
94 installerListener,
95 Long.class,
Ray Milkey18b44ac2014-08-22 08:29:47 -070096 MatchActionOperations.class);
97
Brian O'Connorab3e9e62014-09-09 23:45:55 -070098
99 final Coordinator coordinator = new Coordinator();
100 coordinator.start();
101 installSetReplyChannel = datagrid.addListener(
102 "onos.matchaction.installSetReplyChannel",
103 coordinator,
Ray Milkey18b44ac2014-08-22 08:29:47 -0700104 String.class,
105 SwitchResultList.class);
106
Ray Milkeya313cde2014-09-05 09:02:52 -0700107 // TODO Single instance for now, should be a work queue of some sort eventually
Brian O'Connorab3e9e62014-09-09 23:45:55 -0700108 final InstallerWorker installer = new InstallerWorker();
Ray Milkey18b44ac2014-08-22 08:29:47 -0700109 installer.start();
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700110
Ray Milkey18b44ac2014-08-22 08:29:47 -0700111 }
112
Ray Milkeya313cde2014-09-05 09:02:52 -0700113 /**
114 * Installs a set of MatchActionOperations.
115 *
116 * @param matchSet the set of MatchActions to install
117 * @return identifier of the installed operations
118 */
Ray Milkey18b44ac2014-08-22 08:29:47 -0700119 public MatchActionOperationsId installMatchActionOperations(MatchActionOperations matchSet) {
120 if (checkResolved(matchSet)) {
121 matchSet.setState(MatchActionOperationsState.RESOLVED);
122 } else {
123 matchSet.setState(MatchActionOperationsState.INIT);
124 }
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700125 log.trace("MatchActionsOperations set added: {} {} {}",
126 matchSet.getOperationsId(),
127 matchSet.getState(),
128 matchSet.toString());
Ray Milkey18b44ac2014-08-22 08:29:47 -0700129 matchSetMap.put(matchSet.getOperationsId(), matchSet);
130 if (matchSet.getState() == MatchActionOperationsState.RESOLVED) {
131 resolvedQueue.add(matchSet.getOperationsId());
132 }
133 return matchSet.getOperationsId();
134 }
135
Ray Milkeya313cde2014-09-05 09:02:52 -0700136 /**
137 * Returns the state of a set of operations.
138 *
139 * @param matchSetId identifier of the MatchActionOperations being queried.
140 * @return state of the given operations
141 */
Ray Milkey18b44ac2014-08-22 08:29:47 -0700142 public MatchActionOperationsState getMatchActionOperationsState(MatchActionOperationsId matchSetId) {
143 MatchActionOperations set = matchSetMap.get(matchSetId);
144 return (set == null) ? null : set.getState();
145 }
146
Ray Milkeya313cde2014-09-05 09:02:52 -0700147 /**
148 * Checks if a given set of operations has all of its dependencies resolved.
149 *
150 * @param matchSet Operations set to check
151 * @return true if all dependencies are resolved, false otherwise
152 */
153 private boolean checkResolved(MatchActionOperations matchSet) {
Ray Milkey18b44ac2014-08-22 08:29:47 -0700154 boolean resolved = true;
155 for (MatchActionOperationsId setId : matchSet.getDependencies()) {
156 MatchActionOperations set = matchSetMap.get(setId);
157 if (set == null || set.getState() != MatchActionOperationsState.RESOLVED) {
158 resolved = false;
159 break;
160 }
161 }
162 return resolved;
163 }
164
Ray Milkeya313cde2014-09-05 09:02:52 -0700165 /**
166 * Producer class for MatchActionOperations. An instance of this runs on
167 * each ONOS node. Requests come in via the resolved queue, and are
168 * distributed to workers running on each ONOS instance via a channel.
169 */
170 private final class Coordinator extends Thread
Ray Milkey18b44ac2014-08-22 08:29:47 -0700171 implements IEventChannelListener<String, SwitchResultList> {
172
Ray Milkeya313cde2014-09-05 09:02:52 -0700173 private final Map<MatchActionOperationsId,
174 Map<Dpid, SwitchResult>>
175 pendingMatchActionOperations = new HashMap<>();
Ray Milkey18b44ac2014-08-22 08:29:47 -0700176
Ray Milkeya313cde2014-09-05 09:02:52 -0700177 /**
178 * Default constructor.
179 */
180 Coordinator() {
Brian O'Connorab3e9e62014-09-09 23:45:55 -0700181 // nothing to initialize
Ray Milkey18b44ac2014-08-22 08:29:47 -0700182 }
183
184 @Override
185 public void run() {
Ray Milkeya313cde2014-09-05 09:02:52 -0700186 //noinspection InfiniteLoopStatement - for IntelliJ
Ray Milkey18b44ac2014-08-22 08:29:47 -0700187 while (true) {
188 // 1. Remove MatchActionOperations(s) from the Global Resolved Queue
189 try {
190 MatchActionOperationsId setId = resolvedQueue.take();
191 processSet(setId);
192 } catch (InterruptedException e) {
193 log.warn("Error taking from resolved queue: {}", e.getMessage());
194 }
195 }
196 }
197
Ray Milkeya313cde2014-09-05 09:02:52 -0700198 /**
199 * Processes an inbound MatchActionOperations object.
200 *
201 * @param setId Identifier of the MatchActionOperations object
202 */
Ray Milkey18b44ac2014-08-22 08:29:47 -0700203 private void processSet(MatchActionOperationsId setId) {
204 MatchActionOperations matchSet = matchSetMap.get(setId);
205 matchSet.setState(MatchActionOperationsState.PENDING);
206 matchSetMap.put(setId, matchSet);
207
208 // TODO apply updates to in-memory flow table and resolve conflicts
209 // TODO generate apply and undo sets, using MatchActionOperations for now...
210
211 // build pending switches set for coordinator tracking
212 Map<Dpid, SwitchResult> switches = new HashMap<>();
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700213 for (MatchActionOperationEntry matchActionOp : matchSet.getOperations()) {
214 MatchAction matchAction = matchActionOp.getTarget();
215 SwitchPort sw = matchAction.getSwitchPort();
Ray Milkey18b44ac2014-08-22 08:29:47 -0700216 switches.put(sw.getDpid(), new SwitchResult(setId, sw.getDpid()));
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700217 switch(matchActionOp.getOperator()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700218 case MODIFY:
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700219 case ADD:
220 matchActionMap.put(matchAction.getId(), matchAction);
221 break;
222 case REMOVE:
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700223 // TODO we may want to be more careful when removing MatchActions
224 matchActionMap.remove(matchAction.getId());
225 break;
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700226 default:
227 throw new UnsupportedOperationException(
228 "Unsupported MatchAction operation" +
229 matchActionOp.getOperator().toString());
230 }
Ray Milkey18b44ac2014-08-22 08:29:47 -0700231 }
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700232 pendingMatchActionOperations.put(setId, switches);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700233
234 // distribute apply/undo sets to cluster
Brian O'Connorab3e9e62014-09-09 23:45:55 -0700235 log.trace("MatchAction Coordinator distributing set: {}", matchSet);
236 installSetChannel.addTransientEntry(setId.getId(), matchSet);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700237 }
238
239 @Override
240 public void entryAdded(SwitchResultList value) {
241 updateSwitchResults(value);
242 }
243
244 @Override
245 public void entryRemoved(SwitchResultList value) {
246 // noop
247 }
248
249 @Override
250 public void entryUpdated(SwitchResultList value) {
251 updateSwitchResults(value);
252 }
253
Ray Milkeya313cde2014-09-05 09:02:52 -0700254 /**
255 * Processes the response from a consumer.
256 *
257 * @param results List of switches modified by the consumer
258 */
Ray Milkey18b44ac2014-08-22 08:29:47 -0700259 private void updateSwitchResults(SwitchResultList results) {
260 if (results == null || results.size() == 0) {
261 return;
262 }
263 MatchActionOperationsId matchSetId = results.get(0).getMatchActionOperationsId();
264
265 // apply updates from results list
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700266 Map<Dpid, SwitchResult> resultMap = pendingMatchActionOperations.get(matchSetId);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700267 for (SwitchResult result : results) {
268 SwitchResult resultToUpdate = resultMap.get(result.getSwitch());
269 if (resultToUpdate != null) {
270 resultToUpdate.setStatus(result.getStatus());
271 }
272 // else {
273 // TODO error!
274 // }
275 }
276
277 // check to see the overall outcome of the install operation
278 SwitchResult.Status setResult = SwitchResult.Status.SUCCESS;
279 for (SwitchResult result : resultMap.values()) {
280 if (result.getStatus().equals(SwitchResult.Status.FAILURE)) {
281 setResult = SwitchResult.Status.FAILURE;
282 // if any switch fails, we fail the installation
283 break;
284 } else if (!setResult.equals(SwitchResult.Status.FAILURE)
285 && result.getStatus().equals(SwitchResult.Status.UNKNOWN)) {
286 setResult = SwitchResult.Status.UNKNOWN;
287 }
288 }
289 switch (setResult) {
290 case SUCCESS:
291 // mark MatchActionOperations as INSTALLED
292 MatchActionOperations matchSet = matchSetMap.get(matchSetId);
293 matchSet.setState(MatchActionOperationsState.INSTALLED);
294 matchSetMap.replace(matchSetId, matchSet);
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700295 pendingMatchActionOperations.remove(matchSetId);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700296
297 // TODO update dependent sets as needed
298 break;
299 case FAILURE:
300 // mark MatchActionOperations as FAILED
301 matchSet = matchSetMap.get(matchSetId);
302 matchSet.setState(MatchActionOperationsState.FAILED);
303 matchSetMap.replace(matchSetId, matchSet);
304
305 // TODO instruct installers to install Undo set
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700306 // TODO the pendingMatchActionOperations state needs to be cleaned-up
Ray Milkey18b44ac2014-08-22 08:29:47 -0700307 break;
308 case UNKNOWN:
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700309 // FALLTHROUGH
Ray Milkey18b44ac2014-08-22 08:29:47 -0700310 default:
311 // noop, still waiting for results
312 // TODO: check to see if installers are dead after timeout
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700313 break;
Ray Milkey18b44ac2014-08-22 08:29:47 -0700314 }
315 }
316 }
317
Ray Milkeya313cde2014-09-05 09:02:52 -0700318 /**
319 * Worker thread that pushes MatchActionOperations to the switches via
320 * the FlowPusher.
321 */
322 private class InstallerWorker extends Thread {
323
324 /**
325 * Default constructor.
326 */
327 InstallerWorker() {
328 // nothing to initialize
329 }
Ray Milkey18b44ac2014-08-22 08:29:47 -0700330
331 // Note: we should consider using an alternative representation for
332 // apply sets
Ray Milkeya313cde2014-09-05 09:02:52 -0700333
334 /**
335 * Installs a set of MatchActionOperations using the Flow Pusher.
336 *
337 * @param matchSet set of MatchActions to install
338 */
339 private void install(MatchActionOperations matchSet) {
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700340 Set<Long> masterDpids = provider.getAllMasterSwitchDpids();
Ray Milkey18b44ac2014-08-22 08:29:47 -0700341
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700342 Set<MatchActionOperationEntry> installSet = new HashSet<>();
343 Set<Dpid> modifiedSwitches = new HashSet<>();
Ray Milkey18b44ac2014-08-22 08:29:47 -0700344
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700345 for (MatchActionOperationEntry matchActionOp : matchSet.getOperations()) {
346 MatchAction matchAction = matchActionOp.getTarget();
347 Dpid dpid = matchAction.getSwitchPort().getDpid();
348 if (masterDpids.contains(dpid.value())) {
349 // only install if we are the master
350 // TODO this optimization will introduce some nice race
351 // conditions on failure requiring mastership change
352 installSet.add(matchActionOp);
353 modifiedSwitches.add(dpid);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700354 }
Ray Milkey18b44ac2014-08-22 08:29:47 -0700355 }
356
357 // push flow entries to switches
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700358 pusher.pushMatchActions(installSet);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700359
360 // insert a barrier after each phase on each modifiedSwitch
361 // wait for confirmation messages before proceeding
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700362 List<Pair<Dpid, OFMessageFuture<OFBarrierReply>>> barriers = new ArrayList<>();
363 for (Dpid dpid : modifiedSwitches) {
364 barriers.add(Pair.of(dpid, pusher.barrierAsync(dpid)));
Ray Milkey18b44ac2014-08-22 08:29:47 -0700365 }
366 List<SwitchResult> switchResults = new ArrayList<>();
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700367 for (Pair<Dpid, OFMessageFuture<OFBarrierReply>> pair : barriers) {
368 Dpid dpid = pair.getLeft();
Ray Milkey18b44ac2014-08-22 08:29:47 -0700369 OFMessageFuture<OFBarrierReply> future = pair.getRight();
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700370 SwitchResult switchResult = new SwitchResult(matchSet.getOperationsId(),
371 dpid);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700372 try {
373 future.get();
374 switchResult.setStatus(SwitchResult.Status.SUCCESS);
375 } catch (InterruptedException | ExecutionException e) {
Brian O'Connoraa5a7b92014-08-29 14:45:18 -0700376 log.error("Barrier message not received for sw: {}", dpid);
Ray Milkey18b44ac2014-08-22 08:29:47 -0700377 switchResult.setStatus(SwitchResult.Status.FAILURE);
378 }
379 switchResults.add(switchResult);
380 }
381
382 // send update message to coordinator
383 // TODO: we might want to use another ID here, i.e. GUID, to avoid
384 // overlap
385 final SwitchResultList switchResultList = new SwitchResultList();
386 switchResultList.addAll(switchResults);
387 installSetReplyChannel.addTransientEntry(matchSet.getOperationsId().toString(),
388 switchResultList);
389 }
390
Ray Milkey18b44ac2014-08-22 08:29:47 -0700391 @Override
392 public void run() {
Ray Milkeya313cde2014-09-05 09:02:52 -0700393 //noinspection InfiniteLoopStatement - for IntelliJ
Ray Milkey18b44ac2014-08-22 08:29:47 -0700394 while (true) {
395 // 1. Remove MatchActionOperations(s) from the Global Resolved Queue
396 try {
397 MatchActionOperations operations = installationWorkQueue.take();
398 install(operations);
399 } catch (InterruptedException e) {
400 log.warn("Error taking from installation queue: {}", e.getMessage());
401 }
402 }
403 }
404 }
405
Ray Milkeya313cde2014-09-05 09:02:52 -0700406 /**
407 * Consumer class for MatchActionOperations. Listens on the MatchAction
408 * channel and places inbound requests on a queue to be handled by the
409 * InstallerWorker threads.
410 */
Ray Milkey18b44ac2014-08-22 08:29:47 -0700411 class Installer
Brian O'Connorab3e9e62014-09-09 23:45:55 -0700412 implements IEventChannelListener<Long, MatchActionOperations> {
Ray Milkey18b44ac2014-08-22 08:29:47 -0700413
414 @Override
415 public void entryAdded(MatchActionOperations value) {
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700416 try {
Brian O'Connorab3e9e62014-09-09 23:45:55 -0700417 log.trace("MatchAction Installer receiving set: {}", value);
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700418 installationWorkQueue.put(value);
419 } catch (InterruptedException e) {
420 log.warn("Error adding to installer work queue: {}",
421 e.getMessage());
422 }
Ray Milkey18b44ac2014-08-22 08:29:47 -0700423 }
424
425 @Override
426 public void entryRemoved(MatchActionOperations value) {
427 // noop
428 }
429
430 @Override
431 public void entryUpdated(MatchActionOperations value) {
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700432 try {
Brian O'Connorab3e9e62014-09-09 23:45:55 -0700433 log.trace("MatchAction Installer receiving set: {}", value);
Brian O'Connor7e2d9142014-09-02 17:24:27 -0700434 installationWorkQueue.put(value);
435 } catch (InterruptedException e) {
436 log.warn("Error adding to installer work queue: {}",
437 e.getMessage());
438 }
Ray Milkey18b44ac2014-08-22 08:29:47 -0700439 }
440 }
441
Ray Milkey18b44ac2014-08-22 08:29:47 -0700442 @Override
443 public boolean addMatchAction(MatchAction matchAction) {
444 return false;
445 }
446
447 @Override
448 public Set<MatchAction> getMatchActions() {
Ray Milkey80dc8c92014-09-03 13:49:46 -0700449 return new HashSet<>(matchActionMap.values());
Ray Milkey18b44ac2014-08-22 08:29:47 -0700450 }
451
452 @Override
453 public boolean executeOperations(final MatchActionOperations operations) {
454 installMatchActionOperations(operations);
Ray Milkey80dc8c92014-09-03 13:49:46 -0700455 // TODO how to generate an actual error response here
456 return true;
Ray Milkey18b44ac2014-08-22 08:29:47 -0700457 }
458
459 @Override
460 public void setConflictDetectionPolicy(ConflictDetectionPolicy policy) {
461 // TODO Auto-generated method stub
462
463 }
464
465 @Override
466 public ConflictDetectionPolicy getConflictDetectionPolicy() {
467 // TODO Auto-generated method stub
468 return null;
469 }
470
471 @Override
472 public void addEventListener(EventListener listener) {
473 // TODO Auto-generated method stub
474
475 }
476
477 @Override
478 public void removeEventListener(EventListener listener) {
479 // TODO Auto-generated method stub
480
481 }
482
483 @Override
484 public IdGenerator<MatchActionId> getMatchActionIdGenerator() {
Ray Milkey626a2b12014-09-02 11:19:06 -0700485 return matchActionIdGenerator;
Ray Milkey18b44ac2014-08-22 08:29:47 -0700486 }
487
488 @Override
489 public IdGenerator<MatchActionOperationsId> getMatchActionOperationsIdGenerator() {
Ray Milkey626a2b12014-09-02 11:19:06 -0700490 return matchActionOperationsIdGenerator;
Ray Milkey18b44ac2014-08-22 08:29:47 -0700491 }
492
493}