blob: 468bb07e18f601319da900c2ba214b6932e8e377 [file] [log] [blame]
Jonathan Hartd82f20d2013-02-21 18:04:24 -08001package net.onrc.onos.registry.controller;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08002
Jonathan Hartbd181b62013-02-17 16:05:38 -08003import java.io.IOException;
Jonathan Hartedd6a442013-02-20 15:22:06 -08004import java.io.UnsupportedEncodingException;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08005import java.util.ArrayList;
6import java.util.Collection;
Jonathan Hart3d7730a2013-02-22 11:51:17 -08007import java.util.Collections;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08008import java.util.HashMap;
Jonathan Hartedd6a442013-02-20 15:22:06 -08009import java.util.List;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080010import java.util.Map;
11
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080012import net.floodlightcontroller.core.module.FloodlightModuleContext;
13import net.floodlightcontroller.core.module.FloodlightModuleException;
14import net.floodlightcontroller.core.module.IFloodlightModule;
15import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080016import net.floodlightcontroller.restserver.IRestApiService;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080017
Jonathan Hartedd6a442013-02-20 15:22:06 -080018import org.apache.zookeeper.CreateMode;
Jonathan Hartbd181b62013-02-17 16:05:38 -080019import org.apache.zookeeper.WatchedEvent;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080020import org.apache.zookeeper.Watcher.Event.KeeperState;
Jonathan Hartbd181b62013-02-17 16:05:38 -080021import org.openflow.util.HexString;
22import org.slf4j.Logger;
23import org.slf4j.LoggerFactory;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080024
Jonathan Hartd10008d2013-02-23 17:04:08 -080025import com.google.common.base.Charsets;
Jonathan Hartbd181b62013-02-17 16:05:38 -080026import com.netflix.curator.RetryPolicy;
27import com.netflix.curator.framework.CuratorFramework;
28import com.netflix.curator.framework.CuratorFrameworkFactory;
29import com.netflix.curator.framework.api.CuratorWatcher;
Jonathan Hartedd6a442013-02-20 15:22:06 -080030import com.netflix.curator.framework.recipes.cache.ChildData;
31import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
32import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080033import com.netflix.curator.framework.recipes.cache.PathChildrenCacheEvent;
34import com.netflix.curator.framework.recipes.cache.PathChildrenCacheListener;
Jonathan Hartbd181b62013-02-17 16:05:38 -080035import com.netflix.curator.framework.recipes.leader.LeaderLatch;
36import com.netflix.curator.framework.recipes.leader.Participant;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080037import com.netflix.curator.retry.ExponentialBackoffRetry;
Jonathan Hartbd181b62013-02-17 16:05:38 -080038
Jonathan Hartbd766972013-02-22 15:13:03 -080039public class ZookeeperRegistry implements IFloodlightModule, IControllerRegistryService {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080040
Jonathan Hartbd766972013-02-22 15:13:03 -080041 protected static Logger log = LoggerFactory.getLogger(ZookeeperRegistry.class);
42 protected String controllerId = null;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080043
Jonathan Hart3d7730a2013-02-22 11:51:17 -080044 protected IRestApiService restApi;
45
Jonathan Hartbd181b62013-02-17 16:05:38 -080046 //TODO read this from configuration
47 protected String connectionString = "localhost:2181";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080048
49
Jonathan Hartbd181b62013-02-17 16:05:38 -080050 private final String namespace = "onos";
Jonathan Hartedd6a442013-02-20 15:22:06 -080051 private final String switchLatchesPath = "/switches";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080052 private final String controllerPath = "/controllers";
Jonathan Hartbd181b62013-02-17 16:05:38 -080053
54 protected CuratorFramework client;
Jonathan Hartedd6a442013-02-20 15:22:06 -080055
Jonathan Hartedd6a442013-02-20 15:22:06 -080056 protected PathChildrenCache controllerCache;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080057 protected PathChildrenCache switchCache;
Jonathan Hartbd181b62013-02-17 16:05:38 -080058
59 protected Map<String, LeaderLatch> switchLatches;
Jonathan Hartd82f20d2013-02-21 18:04:24 -080060 protected Map<String, ControlChangeCallback> switchCallbacks;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080061 protected Map<String, PathChildrenCache> switchPathCaches;
Jonathan Hartbd181b62013-02-17 16:05:38 -080062
Jonathan Hart97801ac2013-02-26 14:29:16 -080063 //Zookeeper performance-related configuration
Jonathan Hartcc957a02013-02-26 10:39:04 -080064 protected static final int sessionTimeout = 2000;
65 protected static final int connectionTimeout = 4000;
Jonathan Hart57080fb2013-02-21 10:55:46 -080066
Jonathan Hartbd181b62013-02-17 16:05:38 -080067 protected class ParamaterizedCuratorWatcher implements CuratorWatcher {
68 private String dpid;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080069 private boolean isLeader = false;
Jonathan Hartbd181b62013-02-17 16:05:38 -080070 private String latchPath;
71
72 public ParamaterizedCuratorWatcher(String dpid, String latchPath){
73 this.dpid = dpid;
74 this.latchPath = latchPath;
75 }
76
77 @Override
Jonathan Hartedd6a442013-02-20 15:22:06 -080078 public synchronized void process(WatchedEvent event) throws Exception {
Jonathan Hartbd181b62013-02-17 16:05:38 -080079 log.debug("Watch Event: {}", event);
80
81 LeaderLatch latch = switchLatches.get(dpid);
82
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080083 if (event.getState() == KeeperState.Disconnected){
84 if (isLeader) {
85 log.debug("Disconnected while leader - lost leadership for {}", dpid);
86
87 isLeader = false;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080088 ControlChangeCallback cb = switchCallbacks.get(dpid);
89 if (cb != null) {
90 //Allow callback to be null if the requester doesn't want a callback
91 cb.controlChanged(HexString.toLong(dpid), false);
92 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080093 }
94 return;
95 }
Jonathan Hartbd181b62013-02-17 16:05:38 -080096
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080097 try {
Jonathan Hartedd6a442013-02-20 15:22:06 -080098
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080099 Participant leader = latch.getLeader();
100
Jonathan Hartbd766972013-02-22 15:13:03 -0800101 if (leader.getId().equals(controllerId) && !isLeader){
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800102 log.debug("Became leader for {}", dpid);
103
104 isLeader = true;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800105 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), true);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800106 }
Jonathan Hartbd766972013-02-22 15:13:03 -0800107 else if (!leader.getId().equals(controllerId) && isLeader){
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800108 log.debug("Lost leadership for {}", dpid);
109
110 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800111 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800112 }
113 } catch (Exception e){
114 if (isLeader){
115 log.debug("Exception checking leadership status. Assume leadship lost for {}",
116 dpid);
117
118 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800119 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800120 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800121 }
122
123 client.getChildren().usingWatcher(this).inBackground().forPath(latchPath);
124 //client.getChildren().usingWatcher(this).forPath(latchPath);
125 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800126 }
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800127
128
129 /*
130 * Listens for changes to the switch znodes in Zookeeper. This maintains the second level of
131 * PathChildrenCaches that hold the controllers contending for each switch - there's one for
132 * each switch.
133 */
134 PathChildrenCacheListener switchPathCacheListener = new PathChildrenCacheListener() {
135 @Override
136 public void childEvent(CuratorFramework client,
137 PathChildrenCacheEvent event) throws Exception {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800138 log.debug("Root switch path cache got {} event", event.getType());
139
140 String strSwitch = null;
141 if (event.getData() != null){
142 log.debug("Event path {}", event.getData().getPath());
143 String[] splitted = event.getData().getPath().split("/");
144 strSwitch = splitted[splitted.length - 1];
145 log.debug("Switch name is {}", strSwitch);
146 }
147
148 switch (event.getType()){
149 case CHILD_ADDED:
150 case CHILD_UPDATED:
151 //Check we have a PathChildrenCache for this child, add one if not
152 if (switchPathCaches.get(strSwitch) == null){
153 PathChildrenCache pc = new PathChildrenCache(client,
154 event.getData().getPath(), true);
155 pc.start(StartMode.NORMAL);
156 switchPathCaches.put(strSwitch, pc);
157 }
158 break;
159 case CHILD_REMOVED:
160 //Remove our PathChildrenCache for this child
161 PathChildrenCache pc = switchPathCaches.remove(strSwitch);
162 pc.close();
163 break;
164 default:
165 //All other events are connection status events. We need to do anything
166 //as the path cache handles these on its own.
167 break;
168 }
169
170 }
171 };
Jonathan Hartedd6a442013-02-20 15:22:06 -0800172
Jonathan Hartbd181b62013-02-17 16:05:38 -0800173
174 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800175 public void requestControl(long dpid, ControlChangeCallback cb) throws RegistryException {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800176
Jonathan Hartbd766972013-02-22 15:13:03 -0800177 if (controllerId == null){
178 throw new RuntimeException("Must register a controller before calling requestControl");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800179 }
180
181 String dpidStr = HexString.toHexString(dpid);
182 String latchPath = switchLatchesPath + "/" + dpidStr;
183
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800184 if (switchLatches.get(dpidStr) != null){
185 throw new RuntimeException("Leader election for switch " + dpidStr +
186 "is already running");
187 }
188
Jonathan Hartbd766972013-02-22 15:13:03 -0800189 LeaderLatch latch = new LeaderLatch(client, latchPath, controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800190 switchLatches.put(dpidStr, latch);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800191 switchCallbacks.put(dpidStr, cb);
192
193 try {
194 //client.getChildren().usingWatcher(watcher).inBackground().forPath(singleLatchPath);
195 client.getChildren().usingWatcher(
196 new ParamaterizedCuratorWatcher(dpidStr, latchPath))
197 .inBackground().forPath(latchPath);
198 latch.start();
199 } catch (Exception e) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800200 log.warn("Error starting leader latch: {}", e.getMessage());
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800201 throw new RegistryException("Error starting leader latch for " + dpidStr, e);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800202 }
203
204 }
205
206 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800207 public void releaseControl(long dpid) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800208
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800209 String dpidStr = HexString.toHexString(dpid);
210
211 LeaderLatch latch = switchLatches.get(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800212 if (latch == null) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800213 log.debug("Trying to release mastership for switch we are not contesting");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800214 return;
215 }
216
217 try {
218 latch.close();
219 } catch (IOException e) {
Jonathan Hart1be46262013-02-20 16:43:51 -0800220 //I think it's OK not to do anything here. Either the node got deleted correctly,
221 //or the connection went down and the node got deleted.
222 } finally {
223 switchLatches.remove(dpidStr);
224 switchCallbacks.remove(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800225 }
226 }
227
228 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800229 public boolean hasControl(long dpid) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800230
Jonathan Hartbd181b62013-02-17 16:05:38 -0800231 LeaderLatch latch = switchLatches.get(HexString.toHexString(dpid));
232
233 if (latch == null) {
234 log.warn("No leader latch for dpid {}", HexString.toHexString(dpid));
235 return false;
236 }
237
Jonathan Hartbd181b62013-02-17 16:05:38 -0800238 try {
Jonathan Hartbd766972013-02-22 15:13:03 -0800239 return latch.getLeader().getId().equals(controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800240 } catch (Exception e) {
241 //TODO swallow exception?
242 return false;
243 }
244 }
245
246 @Override
247 public void setMastershipId(String id) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800248 //TODO remove this method if not needed
249 //controllerId = id;
Jonathan Hartbd181b62013-02-17 16:05:38 -0800250 }
251
252 @Override
253 public String getMastershipId() {
Jonathan Hartbd766972013-02-22 15:13:03 -0800254 return controllerId;
Jonathan Hartbd181b62013-02-17 16:05:38 -0800255 }
256
Jonathan Hartedd6a442013-02-20 15:22:06 -0800257 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800258 public Collection<String> getAllControllers() throws RegistryException {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800259 log.debug("Getting all controllers");
Jonathan Hart1be46262013-02-20 16:43:51 -0800260
Jonathan Hartedd6a442013-02-20 15:22:06 -0800261 List<String> controllers = new ArrayList<String>();
262 for (ChildData data : controllerCache.getCurrentData()){
263
264 String d = null;
265 try {
266 d = new String(data.getData(), "UTF-8");
267 } catch (UnsupportedEncodingException e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800268 throw new RegistryException("Error encoding string", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800269 }
270
271 controllers.add(d);
272 }
273 return controllers;
274 }
275
276 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800277 public void registerController(String id) throws RegistryException {
Jonathan Hartd10008d2013-02-23 17:04:08 -0800278 if (controllerId != null) {
279 throw new RegistryException(
280 "Controller already registered with id " + controllerId);
281 }
Jonathan Hartbd766972013-02-22 15:13:03 -0800282
283 controllerId = id;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800284
Jonathan Hartd10008d2013-02-23 17:04:08 -0800285 byte bytes[] = id.getBytes(Charsets.UTF_8);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800286
287 String path = controllerPath + "/" + id;
288
289 log.info("Registering controller with id {}", id);
290
Jonathan Hart57080fb2013-02-21 10:55:46 -0800291 //Create ephemeral node in controller registry
Jonathan Hartedd6a442013-02-20 15:22:06 -0800292 try {
293 client.create().withProtection().withMode(CreateMode.EPHEMERAL)
294 .forPath(path, bytes);
295 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800296 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800297 }
298 }
299
300 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800301 public String getControllerForSwitch(long dpid) throws RegistryException {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800302 // TODO Work out how we should store this controller/switch data.
303 // The leader latch might be a index to the /controllers collections
304 // which holds more info on the controller (how to talk to it for example).
305
Jonathan Hartedd6a442013-02-20 15:22:06 -0800306 String strDpid = HexString.toHexString(dpid);
307 LeaderLatch latch = switchLatches.get(strDpid);
308
309 if (latch == null){
310 log.warn("Tried to get controller for non-existent switch");
311 return null;
312 }
313
314 Participant leader = null;
315 try {
316 leader = latch.getLeader();
317 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800318 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800319 }
320
321 return leader.getId();
322 }
323
324 @Override
325 public Collection<Long> getSwitchesControlledByController(String controllerId) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800326 //TODO remove this if not needed
Jonathan Hartbd766972013-02-22 15:13:03 -0800327 throw new RuntimeException("Not yet implemented");
Jonathan Hartedd6a442013-02-20 15:22:06 -0800328 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800329
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800330
331 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800332 public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
333 Map<String, List<ControllerRegistryEntry>> data =
334 new HashMap<String, List<ControllerRegistryEntry>>();
335
336 for (Map.Entry<String, PathChildrenCache> entry : switchPathCaches.entrySet()){
337 List<ControllerRegistryEntry> contendingControllers =
338 new ArrayList<ControllerRegistryEntry>();
339
340 if (entry.getValue().getCurrentData().size() < 1){
341 log.info("Switch entry with no leader elections: {}", entry.getKey());
342 continue;
343 }
344
345 for (ChildData d : entry.getValue().getCurrentData()) {
Jonathan Hart97801ac2013-02-26 14:29:16 -0800346
Jonathan Hartd10008d2013-02-23 17:04:08 -0800347 String controllerId = new String(d.getData(), Charsets.UTF_8);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800348
349 String[] splitted = d.getPath().split("-");
350 int sequenceNumber = Integer.parseInt(splitted[splitted.length - 1]);
351
352 contendingControllers.add(new ControllerRegistryEntry(controllerId, sequenceNumber));
353 }
354
355 Collections.sort(contendingControllers);
356 data.put(entry.getKey(), contendingControllers);
357 }
358 return data;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800359 }
360
Jonathan Hartbd181b62013-02-17 16:05:38 -0800361 /*
362 * IFloodlightModule
363 */
364
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800365 @Override
366 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800367 Collection<Class<? extends IFloodlightService>> l =
368 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800369 l.add(IControllerRegistryService.class);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800370 return l;
371 }
372
373 @Override
374 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
375 Map<Class<? extends IFloodlightService>, IFloodlightService> m =
376 new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800377 m.put(IControllerRegistryService.class, this);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800378 return m;
379 }
380
381 @Override
382 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800383 Collection<Class<? extends IFloodlightService>> l =
384 new ArrayList<Class<? extends IFloodlightService>>();
385 l.add(IRestApiService.class);
386 return l;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800387 }
388
389 @Override
390 public void init (FloodlightModuleContext context) throws FloodlightModuleException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800391 log.info("Initialising the Zookeeper Registry - Zookeeper connection required");
392
Jonathan Hart97801ac2013-02-26 14:29:16 -0800393 //Read the Zookeeper connection string from the config
394 Map<String, String> configParams = context.getConfigParams(this);
395 String connectionString = configParams.get("connectionString");
396 if (connectionString != null){
397 this.connectionString = connectionString;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800398 }
Jonathan Hart97801ac2013-02-26 14:29:16 -0800399 log.info("Setting Zookeeper connection string to {}", this.connectionString);
Jonathan Hart57080fb2013-02-21 10:55:46 -0800400
Jonathan Hart97801ac2013-02-26 14:29:16 -0800401 restApi = context.getServiceImpl(IRestApiService.class);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800402
403 switchLatches = new HashMap<String, LeaderLatch>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800404 switchCallbacks = new HashMap<String, ControlChangeCallback>();
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800405 switchPathCaches = new HashMap<String, PathChildrenCache>();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800406
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800407 RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
Jonathan Hart97801ac2013-02-26 14:29:16 -0800408 client = CuratorFrameworkFactory.newClient(this.connectionString,
Jonathan Hartcc957a02013-02-26 10:39:04 -0800409 sessionTimeout, connectionTimeout, retryPolicy);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800410
411 client.start();
412
413 client = client.usingNamespace(namespace);
Jonathan Hart97801ac2013-02-26 14:29:16 -0800414
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800415
Jonathan Hartedd6a442013-02-20 15:22:06 -0800416 controllerCache = new PathChildrenCache(client, controllerPath, true);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800417 switchCache = new PathChildrenCache(client, switchLatchesPath, true);
418 switchCache.getListenable().addListener(switchPathCacheListener);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800419
420 try {
421 controllerCache.start(StartMode.BUILD_INITIAL_CACHE);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800422
423 //Don't prime the cache, we want a notification for each child node in the path
424 switchCache.start(StartMode.NORMAL);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800425 } catch (Exception e) {
426 // TODO Auto-generated catch block
427 e.printStackTrace();
428 }
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800429 }
430
431 @Override
432 public void startUp (FloodlightModuleContext context) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800433 restApi.addRestletRoutable(new RegistryWebRoutable());
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800434 }
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800435
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800436}