Ayaka Koshibe

fixes for mastership handoff race conditions

Change-Id: Ifed733df1bdc3b144b6a341a9322838ea2aacd72
...@@ -104,7 +104,6 @@ implements MastershipService, MastershipAdminService { ...@@ -104,7 +104,6 @@ implements MastershipService, MastershipAdminService {
104 MastershipEvent event = null; 104 MastershipEvent event = null;
105 event = store.relinquishRole( 105 event = store.relinquishRole(
106 clusterService.getLocalNode().id(), deviceId); 106 clusterService.getLocalNode().id(), deviceId);
107 -
108 if (event != null) { 107 if (event != null) {
109 post(event); 108 post(event);
110 } 109 }
...@@ -229,7 +228,8 @@ implements MastershipService, MastershipAdminService { ...@@ -229,7 +228,8 @@ implements MastershipService, MastershipAdminService {
229 return true; 228 return true;
230 } 229 }
231 //else { 230 //else {
232 - //FIXME: break tie for equal-sized clusters, can we use hz's functions? 231 + //FIXME: break tie for equal-sized clusters,
232 + // maybe by number of connected switches
233 // } 233 // }
234 return false; 234 return false;
235 } 235 }
......
...@@ -161,6 +161,9 @@ public class DeviceManager ...@@ -161,6 +161,9 @@ public class DeviceManager
161 @Override 161 @Override
162 public void removeDevice(DeviceId deviceId) { 162 public void removeDevice(DeviceId deviceId) {
163 checkNotNull(deviceId, DEVICE_ID_NULL); 163 checkNotNull(deviceId, DEVICE_ID_NULL);
164 + // XXX is this intended to apply to the full global topology?
165 + // if so, we probably don't want the fact that we aren't
166 + // MASTER to get in the way, as it would do now.
164 DeviceEvent event = store.removeDevice(deviceId); 167 DeviceEvent event = store.removeDevice(deviceId);
165 if (event != null) { 168 if (event != null) {
166 log.info("Device {} administratively removed", deviceId); 169 log.info("Device {} administratively removed", deviceId);
...@@ -203,19 +206,21 @@ public class DeviceManager ...@@ -203,19 +206,21 @@ public class DeviceManager
203 log.info("Device {} connected", deviceId); 206 log.info("Device {} connected", deviceId);
204 // check my Role 207 // check my Role
205 MastershipRole role = mastershipService.requestRoleFor(deviceId); 208 MastershipRole role = mastershipService.requestRoleFor(deviceId);
206 - 209 + log.info("## - our role for {} is {} [master is {}]", deviceId, role,
210 + mastershipService.getMasterFor(deviceId));
207 if (role != MastershipRole.MASTER) { 211 if (role != MastershipRole.MASTER) {
208 // TODO: Do we need to explicitly tell the Provider that 212 // TODO: Do we need to explicitly tell the Provider that
209 // this instance is no longer the MASTER? probably not 213 // this instance is no longer the MASTER? probably not
210 return; 214 return;
211 } 215 }
212 -
213 MastershipTerm term = mastershipService.requestTermService() 216 MastershipTerm term = mastershipService.requestTermService()
214 .getMastershipTerm(deviceId); 217 .getMastershipTerm(deviceId);
218 +
215 if (!term.master().equals(clusterService.getLocalNode().id())) { 219 if (!term.master().equals(clusterService.getLocalNode().id())) {
216 // lost mastership after requestRole told this instance was MASTER. 220 // lost mastership after requestRole told this instance was MASTER.
217 return; 221 return;
218 } 222 }
223 +
219 // tell clock provider if this instance is the master 224 // tell clock provider if this instance is the master
220 deviceClockProviderService.setMastershipTerm(deviceId, term); 225 deviceClockProviderService.setMastershipTerm(deviceId, term);
221 226
...@@ -256,19 +261,32 @@ public class DeviceManager ...@@ -256,19 +261,32 @@ public class DeviceManager
256 // but if I was the last STANDBY connection, etc. and no one else 261 // but if I was the last STANDBY connection, etc. and no one else
257 // was there to mark the device offline, this instance may need to 262 // was there to mark the device offline, this instance may need to
258 // temporarily request for Master Role and mark offline. 263 // temporarily request for Master Role and mark offline.
264 + log.info("## for {} role is {}", deviceId, mastershipService.getLocalRole(deviceId));
259 if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) { 265 if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) {
260 log.debug("Device {} disconnected, but I am not the master", deviceId); 266 log.debug("Device {} disconnected, but I am not the master", deviceId);
261 //let go of ability to be backup 267 //let go of ability to be backup
262 mastershipService.relinquishMastership(deviceId); 268 mastershipService.relinquishMastership(deviceId);
263 return; 269 return;
264 } 270 }
265 - DeviceEvent event = store.markOffline(deviceId);
266 - //relinquish master role and ability to be backup.
267 - mastershipService.relinquishMastership(deviceId);
268 271
269 - if (event != null) { 272 + DeviceEvent event = null;
270 - log.info("Device {} disconnected", deviceId); 273 + try {
271 - post(event); 274 + event = store.markOffline(deviceId);
275 + } catch (IllegalStateException e) {
276 + //there are times when this node will correctly have mastership, BUT
277 + //that isn't reflected in the ClockManager before the device disconnects.
278 + //we want to let go of the device anyways, so make sure this happens.
279 + MastershipTerm term = termService.getMastershipTerm(deviceId);
280 + deviceClockProviderService.setMastershipTerm(deviceId, term);
281 + event = store.markOffline(deviceId);
282 + } finally {
283 + //relinquish master role and ability to be backup.
284 + mastershipService.relinquishMastership(deviceId);
285 +
286 + if (event != null) {
287 + log.info("Device {} disconnected", deviceId);
288 + post(event);
289 + }
272 } 290 }
273 } 291 }
274 292
...@@ -279,7 +297,15 @@ public class DeviceManager ...@@ -279,7 +297,15 @@ public class DeviceManager
279 checkNotNull(portDescriptions, 297 checkNotNull(portDescriptions,
280 "Port descriptions list cannot be null"); 298 "Port descriptions list cannot be null");
281 checkValidity(); 299 checkValidity();
300 + //XXX what's this doing here?
282 this.provider().id(); 301 this.provider().id();
302 +
303 + if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) {
304 + // TODO If we become master, then we'll trigger something to update this
305 + // info to fix any inconsistencies that may result during the handoff.
306 + return;
307 + }
308 +
283 List<DeviceEvent> events = store.updatePorts(this.provider().id(), 309 List<DeviceEvent> events = store.updatePorts(this.provider().id(),
284 deviceId, portDescriptions); 310 deviceId, portDescriptions);
285 for (DeviceEvent event : events) { 311 for (DeviceEvent event : events) {
...@@ -293,6 +319,12 @@ public class DeviceManager ...@@ -293,6 +319,12 @@ public class DeviceManager
293 checkNotNull(deviceId, DEVICE_ID_NULL); 319 checkNotNull(deviceId, DEVICE_ID_NULL);
294 checkNotNull(portDescription, PORT_DESCRIPTION_NULL); 320 checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
295 checkValidity(); 321 checkValidity();
322 +
323 + if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) {
324 + // TODO If we become master, then we'll trigger something to update this
325 + // info to fix any inconsistencies that may result during the handoff.
326 + return;
327 + }
296 DeviceEvent event = store.updatePortStatus(this.provider().id(), 328 DeviceEvent event = store.updatePortStatus(this.provider().id(),
297 deviceId, portDescription); 329 deviceId, portDescription);
298 if (event != null) { 330 if (event != null) {
...@@ -328,27 +360,37 @@ public class DeviceManager ...@@ -328,27 +360,37 @@ public class DeviceManager
328 final DeviceId did = event.subject(); 360 final DeviceId did = event.subject();
329 final NodeId myNodeId = clusterService.getLocalNode().id(); 361 final NodeId myNodeId = clusterService.getLocalNode().id();
330 362
363 + log.info("## got Mastershipevent for dev {}", did);
331 if (myNodeId.equals(event.master())) { 364 if (myNodeId.equals(event.master())) {
332 MastershipTerm term = termService.getMastershipTerm(did); 365 MastershipTerm term = termService.getMastershipTerm(did);
333 366
334 - if (term.master().equals(myNodeId)) { 367 + if (!myNodeId.equals(term.master())) {
335 - // only set the new term if I am the master 368 + // something went wrong in consistency, let go
336 - deviceClockProviderService.setMastershipTerm(did, term); 369 + mastershipService.relinquishMastership(did);
370 + applyRole(did, MastershipRole.STANDBY);
371 + return;
337 } 372 }
338 373
374 + log.info("## setting term for CPS as new master for {}", did);
375 + // only set the new term if I am the master
376 + deviceClockProviderService.setMastershipTerm(did, term);
377 +
339 // FIXME: we should check that the device is connected on our end. 378 // FIXME: we should check that the device is connected on our end.
340 // currently, this is not straight forward as the actual switch 379 // currently, this is not straight forward as the actual switch
341 - // implementation is hidden from the registry. 380 + // implementation is hidden from the registry. Maybe we can ask the
342 - if (!isAvailable(did)) { 381 + // provider.
382 + // if the device is null here, we are the first master to claim the
383 + // device. No worries, the DeviceManager will create one soon.
384 + Device device = getDevice(did);
385 + if ((device != null) && !isAvailable(did)) {
343 //flag the device as online. Is there a better way to do this? 386 //flag the device as online. Is there a better way to do this?
344 - Device device = getDevice(did);
345 store.createOrUpdateDevice(device.providerId(), did, 387 store.createOrUpdateDevice(device.providerId(), did,
346 new DefaultDeviceDescription( 388 new DefaultDeviceDescription(
347 did.uri(), device.type(), device.manufacturer(), 389 did.uri(), device.type(), device.manufacturer(),
348 device.hwVersion(), device.swVersion(), 390 device.hwVersion(), device.swVersion(),
349 device.serialNumber())); 391 device.serialNumber()));
350 } 392 }
351 - 393 + //TODO re-collect device information to fix potential staleness
352 applyRole(did, MastershipRole.MASTER); 394 applyRole(did, MastershipRole.MASTER);
353 } else { 395 } else {
354 applyRole(did, MastershipRole.STANDBY); 396 applyRole(did, MastershipRole.STANDBY);
......
...@@ -16,6 +16,7 @@ import org.onlab.onos.event.EventDeliveryService; ...@@ -16,6 +16,7 @@ import org.onlab.onos.event.EventDeliveryService;
16 import org.onlab.onos.net.ConnectPoint; 16 import org.onlab.onos.net.ConnectPoint;
17 import org.onlab.onos.net.DeviceId; 17 import org.onlab.onos.net.DeviceId;
18 import org.onlab.onos.net.Link; 18 import org.onlab.onos.net.Link;
19 +import org.onlab.onos.net.MastershipRole;
19 import org.onlab.onos.net.device.DeviceEvent; 20 import org.onlab.onos.net.device.DeviceEvent;
20 import org.onlab.onos.net.device.DeviceListener; 21 import org.onlab.onos.net.device.DeviceListener;
21 import org.onlab.onos.net.device.DeviceService; 22 import org.onlab.onos.net.device.DeviceService;
...@@ -139,11 +140,17 @@ public class LinkManager ...@@ -139,11 +140,17 @@ public class LinkManager
139 140
140 @Override 141 @Override
141 public void removeLinks(ConnectPoint connectPoint) { 142 public void removeLinks(ConnectPoint connectPoint) {
143 + if (deviceService.getRole(connectPoint.deviceId()) != MastershipRole.MASTER) {
144 + return;
145 + }
142 removeLinks(getLinks(connectPoint)); 146 removeLinks(getLinks(connectPoint));
143 } 147 }
144 148
145 @Override 149 @Override
146 public void removeLinks(DeviceId deviceId) { 150 public void removeLinks(DeviceId deviceId) {
151 + if (deviceService.getRole(deviceId) != MastershipRole.MASTER) {
152 + return;
153 + }
147 removeLinks(getDeviceLinks(deviceId)); 154 removeLinks(getDeviceLinks(deviceId));
148 } 155 }
149 156
...@@ -189,6 +196,15 @@ public class LinkManager ...@@ -189,6 +196,15 @@ public class LinkManager
189 public void linkDetected(LinkDescription linkDescription) { 196 public void linkDetected(LinkDescription linkDescription) {
190 checkNotNull(linkDescription, LINK_DESC_NULL); 197 checkNotNull(linkDescription, LINK_DESC_NULL);
191 checkValidity(); 198 checkValidity();
199 +
200 + ConnectPoint src = linkDescription.src();
201 + ConnectPoint dst = linkDescription.dst();
202 + // if we aren't master for the device associated with the ConnectPoint
203 + // we probably shouldn't be doing this.
204 + if ((deviceService.getRole(src.deviceId()) != MastershipRole.MASTER) ||
205 + (deviceService.getRole(dst.deviceId()) != MastershipRole.MASTER)) {
206 + return;
207 + }
192 LinkEvent event = store.createOrUpdateLink(provider().id(), 208 LinkEvent event = store.createOrUpdateLink(provider().id(),
193 linkDescription); 209 linkDescription);
194 if (event != null) { 210 if (event != null) {
...@@ -201,6 +217,15 @@ public class LinkManager ...@@ -201,6 +217,15 @@ public class LinkManager
201 public void linkVanished(LinkDescription linkDescription) { 217 public void linkVanished(LinkDescription linkDescription) {
202 checkNotNull(linkDescription, LINK_DESC_NULL); 218 checkNotNull(linkDescription, LINK_DESC_NULL);
203 checkValidity(); 219 checkValidity();
220 +
221 + ConnectPoint src = linkDescription.src();
222 + ConnectPoint dst = linkDescription.dst();
223 + // if we aren't master for the device associated with the ConnectPoint
224 + // we probably shouldn't be doing this.
225 + if ((deviceService.getRole(src.deviceId()) != MastershipRole.MASTER) ||
226 + (deviceService.getRole(dst.deviceId()) != MastershipRole.MASTER)) {
227 + return;
228 + }
204 LinkEvent event = store.removeLink(linkDescription.src(), 229 LinkEvent event = store.removeLink(linkDescription.src(),
205 linkDescription.dst()); 230 linkDescription.dst());
206 if (event != null) { 231 if (event != null) {
...@@ -213,6 +238,11 @@ public class LinkManager ...@@ -213,6 +238,11 @@ public class LinkManager
213 public void linksVanished(ConnectPoint connectPoint) { 238 public void linksVanished(ConnectPoint connectPoint) {
214 checkNotNull(connectPoint, "Connect point cannot be null"); 239 checkNotNull(connectPoint, "Connect point cannot be null");
215 checkValidity(); 240 checkValidity();
241 + // if we aren't master for the device associated with the ConnectPoint
242 + // we probably shouldn't be doing this.
243 + if (deviceService.getRole(connectPoint.deviceId()) != MastershipRole.MASTER) {
244 + return;
245 + }
216 log.info("Links for connection point {} vanished", connectPoint); 246 log.info("Links for connection point {} vanished", connectPoint);
217 removeLinks(getLinks(connectPoint)); 247 removeLinks(getLinks(connectPoint));
218 } 248 }
...@@ -221,6 +251,11 @@ public class LinkManager ...@@ -221,6 +251,11 @@ public class LinkManager
221 public void linksVanished(DeviceId deviceId) { 251 public void linksVanished(DeviceId deviceId) {
222 checkNotNull(deviceId, DEVICE_ID_NULL); 252 checkNotNull(deviceId, DEVICE_ID_NULL);
223 checkValidity(); 253 checkValidity();
254 + // if we aren't master for the device associated with the ConnectPoint
255 + // we probably shouldn't be doing this.
256 + if (deviceService.getRole(deviceId) != MastershipRole.MASTER) {
257 + return;
258 + }
224 log.info("Links for device {} vanished", deviceId); 259 log.info("Links for device {} vanished", deviceId);
225 removeLinks(getDeviceLinks(deviceId)); 260 removeLinks(getDeviceLinks(deviceId));
226 } 261 }
......
...@@ -59,6 +59,7 @@ public class LinkManagerTest { ...@@ -59,6 +59,7 @@ public class LinkManagerTest {
59 protected LinkProviderService providerService; 59 protected LinkProviderService providerService;
60 protected TestProvider provider; 60 protected TestProvider provider;
61 protected TestListener listener = new TestListener(); 61 protected TestListener listener = new TestListener();
62 + protected DeviceManager devmgr = new TestDeviceManager();
62 63
63 @Before 64 @Before
64 public void setUp() { 65 public void setUp() {
...@@ -68,7 +69,7 @@ public class LinkManagerTest { ...@@ -68,7 +69,7 @@ public class LinkManagerTest {
68 registry = mgr; 69 registry = mgr;
69 mgr.store = new SimpleLinkStore(); 70 mgr.store = new SimpleLinkStore();
70 mgr.eventDispatcher = new TestEventDispatcher(); 71 mgr.eventDispatcher = new TestEventDispatcher();
71 - mgr.deviceService = new DeviceManager(); 72 + mgr.deviceService = devmgr;
72 mgr.activate(); 73 mgr.activate();
73 74
74 service.addListener(listener); 75 service.addListener(listener);
...@@ -259,4 +260,11 @@ public class LinkManagerTest { ...@@ -259,4 +260,11 @@ public class LinkManagerTest {
259 } 260 }
260 } 261 }
261 262
263 + private static class TestDeviceManager extends DeviceManager {
264 + @Override
265 + public MastershipRole getRole(DeviceId deviceId) {
266 + return MastershipRole.MASTER;
267 + }
268 + }
269 +
262 } 270 }
......
...@@ -44,6 +44,8 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid ...@@ -44,6 +44,8 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid
44 @Override 44 @Override
45 public Timestamp getTimestamp(DeviceId deviceId) { 45 public Timestamp getTimestamp(DeviceId deviceId) {
46 MastershipTerm term = deviceMastershipTerms.get(deviceId); 46 MastershipTerm term = deviceMastershipTerms.get(deviceId);
47 + log.info("term info for {} is: {}", deviceId, term);
48 +
47 if (term == null) { 49 if (term == null) {
48 throw new IllegalStateException("Requesting timestamp for a deviceId without mastership"); 50 throw new IllegalStateException("Requesting timestamp for a deviceId without mastership");
49 } 51 }
...@@ -52,6 +54,7 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid ...@@ -52,6 +54,7 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid
52 54
53 @Override 55 @Override
54 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { 56 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
57 + log.info("adding term info {} {}", deviceId, term.master());
55 deviceMastershipTerms.put(deviceId, term); 58 deviceMastershipTerms.put(deviceId, term);
56 } 59 }
57 } 60 }
......
...@@ -390,6 +390,7 @@ public class GossipDeviceStore ...@@ -390,6 +390,7 @@ public class GossipDeviceStore
390 List<PortDescription> portDescriptions) { 390 List<PortDescription> portDescriptions) {
391 391
392 final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId); 392 final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId);
393 + log.info("timestamp for {} {}", deviceId, newTimestamp);
393 394
394 final Timestamped<List<PortDescription>> timestampedInput 395 final Timestamped<List<PortDescription>> timestampedInput
395 = new Timestamped<>(portDescriptions, newTimestamp); 396 = new Timestamped<>(portDescriptions, newTimestamp);
......
...@@ -360,7 +360,14 @@ public class GossipLinkStore ...@@ -360,7 +360,14 @@ public class GossipLinkStore
360 final LinkKey key = linkKey(src, dst); 360 final LinkKey key = linkKey(src, dst);
361 361
362 DeviceId dstDeviceId = dst.deviceId(); 362 DeviceId dstDeviceId = dst.deviceId();
363 - Timestamp timestamp = deviceClockService.getTimestamp(dstDeviceId); 363 + Timestamp timestamp = null;
364 + try {
365 + timestamp = deviceClockService.getTimestamp(dstDeviceId);
366 + } catch (IllegalStateException e) {
367 + //there are times when this is called before mastership
368 + // handoff correctly completes.
369 + return null;
370 + }
364 371
365 LinkEvent event = removeLinkInternal(key, timestamp); 372 LinkEvent event = removeLinkInternal(key, timestamp);
366 373
......
...@@ -29,7 +29,10 @@ import org.onlab.onos.store.serializers.KryoSerializer; ...@@ -29,7 +29,10 @@ import org.onlab.onos.store.serializers.KryoSerializer;
29 import org.onlab.util.KryoPool; 29 import org.onlab.util.KryoPool;
30 30
31 import com.google.common.collect.ImmutableSet; 31 import com.google.common.collect.ImmutableSet;
32 +import com.hazelcast.core.EntryEvent;
33 +import com.hazelcast.core.EntryListener;
32 import com.hazelcast.core.IAtomicLong; 34 import com.hazelcast.core.IAtomicLong;
35 +import com.hazelcast.core.MapEvent;
33 36
34 import static org.onlab.onos.net.MastershipRole.*; 37 import static org.onlab.onos.net.MastershipRole.*;
35 38
...@@ -78,7 +81,7 @@ implements MastershipStore { ...@@ -78,7 +81,7 @@ implements MastershipStore {
78 roleMap = new SMap(theInstance.getMap("nodeRoles"), this.serializer); 81 roleMap = new SMap(theInstance.getMap("nodeRoles"), this.serializer);
79 terms = new SMap(theInstance.getMap("terms"), this.serializer); 82 terms = new SMap(theInstance.getMap("terms"), this.serializer);
80 clusterSize = theInstance.getAtomicLong("clustersize"); 83 clusterSize = theInstance.getAtomicLong("clustersize");
81 - // roleMap.addEntryListener(new RemoteMasterShipEventHandler(), true); 84 + roleMap.addEntryListener((new RemoteMasterShipEventHandler()), true);
82 85
83 log.info("Started"); 86 log.info("Started");
84 } 87 }
...@@ -207,6 +210,7 @@ implements MastershipStore { ...@@ -207,6 +210,7 @@ implements MastershipStore {
207 rv.reassign(local, NONE, STANDBY); 210 rv.reassign(local, NONE, STANDBY);
208 roleMap.put(deviceId, rv); 211 roleMap.put(deviceId, rv);
209 terms.putIfAbsent(deviceId, INIT); 212 terms.putIfAbsent(deviceId, INIT);
213 +
210 break; 214 break;
211 case NONE: 215 case NONE:
212 //claim mastership 216 //claim mastership
...@@ -289,7 +293,8 @@ implements MastershipStore { ...@@ -289,7 +293,8 @@ implements MastershipStore {
289 } 293 }
290 294
291 //helper to fetch a new master candidate for a given device. 295 //helper to fetch a new master candidate for a given device.
292 - private MastershipEvent reelect(NodeId current, DeviceId deviceId, RoleValue rv) { 296 + private MastershipEvent reelect(
297 + NodeId current, DeviceId deviceId, RoleValue rv) {
293 298
294 //if this is an queue it'd be neater. 299 //if this is an queue it'd be neater.
295 NodeId backup = null; 300 NodeId backup = null;
...@@ -301,17 +306,18 @@ implements MastershipStore { ...@@ -301,17 +306,18 @@ implements MastershipStore {
301 } 306 }
302 307
303 if (backup == null) { 308 if (backup == null) {
309 + log.info("{} giving up and going to NONE for {}", current, deviceId);
304 rv.remove(MASTER, current); 310 rv.remove(MASTER, current);
305 roleMap.put(deviceId, rv); 311 roleMap.put(deviceId, rv);
306 return null; 312 return null;
307 } else { 313 } else {
314 + log.info("{} trying to pass mastership for {} to {}", current, deviceId, backup);
308 rv.replace(current, backup, MASTER); 315 rv.replace(current, backup, MASTER);
309 rv.reassign(backup, STANDBY, NONE); 316 rv.reassign(backup, STANDBY, NONE);
310 roleMap.put(deviceId, rv); 317 roleMap.put(deviceId, rv);
311 Integer term = terms.get(deviceId); 318 Integer term = terms.get(deviceId);
312 terms.put(deviceId, ++term); 319 terms.put(deviceId, ++term);
313 - return new MastershipEvent( 320 + return new MastershipEvent(MASTER_CHANGED, deviceId, backup);
314 - MASTER_CHANGED, deviceId, backup);
315 } 321 }
316 } 322 }
317 323
...@@ -346,30 +352,51 @@ implements MastershipStore { ...@@ -346,30 +352,51 @@ implements MastershipStore {
346 352
347 //adds or updates term information. 353 //adds or updates term information.
348 private void updateTerm(DeviceId deviceId) { 354 private void updateTerm(DeviceId deviceId) {
349 - Integer term = terms.get(deviceId); 355 + terms.lock(deviceId);
350 - if (term == null) { 356 + try {
351 - terms.put(deviceId, INIT); 357 + Integer term = terms.get(deviceId);
352 - } else { 358 + if (term == null) {
353 - terms.put(deviceId, ++term); 359 + terms.put(deviceId, INIT);
360 + } else {
361 + terms.put(deviceId, ++term);
362 + }
363 + } finally {
364 + terms.unlock(deviceId);
354 } 365 }
355 } 366 }
356 367
357 - private class RemoteMasterShipEventHandler extends RemoteEventHandler<DeviceId, NodeId> { 368 + private class RemoteMasterShipEventHandler implements EntryListener<DeviceId, RoleValue> {
369 +
370 + @Override
371 + public void entryAdded(EntryEvent<DeviceId, RoleValue> event) {
372 + }
373 +
374 + @Override
375 + public void entryRemoved(EntryEvent<DeviceId, RoleValue> event) {
376 + }
377 +
378 + @Override
379 + public void entryUpdated(EntryEvent<DeviceId, RoleValue> event) {
380 + NodeId myId = clusterService.getLocalNode().id();
381 + NodeId node = event.getValue().get(MASTER);
382 + if (myId.equals(node)) {
383 + // XXX or do we just let it get sent and caught by ourself?
384 + return;
385 + }
386 + notifyDelegate(new MastershipEvent(
387 + MASTER_CHANGED, event.getKey(), event.getValue().get(MASTER)));
388 + }
358 389
359 @Override 390 @Override
360 - protected void onAdd(DeviceId deviceId, NodeId nodeId) { 391 + public void entryEvicted(EntryEvent<DeviceId, RoleValue> event) {
361 - notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
362 } 392 }
363 393
364 @Override 394 @Override
365 - protected void onRemove(DeviceId deviceId, NodeId nodeId) { 395 + public void mapEvicted(MapEvent event) {
366 - //notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
367 } 396 }
368 397
369 @Override 398 @Override
370 - protected void onUpdate(DeviceId deviceId, NodeId oldNodeId, NodeId nodeId) { 399 + public void mapCleared(MapEvent event) {
371 - //only addition indicates a change in mastership
372 - //notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
373 } 400 }
374 } 401 }
375 402
......
...@@ -94,7 +94,6 @@ public final class KryoPoolUtil { ...@@ -94,7 +94,6 @@ public final class KryoPoolUtil {
94 .register(ConnectPoint.class, new ConnectPointSerializer()) 94 .register(ConnectPoint.class, new ConnectPointSerializer())
95 .register(DefaultLink.class, new DefaultLinkSerializer()) 95 .register(DefaultLink.class, new DefaultLinkSerializer())
96 .register(MastershipTerm.class, new MastershipTermSerializer()) 96 .register(MastershipTerm.class, new MastershipTermSerializer())
97 - .register(MastershipRole.class, new MastershipRoleSerializer())
98 .register(HostLocation.class, new HostLocationSerializer()) 97 .register(HostLocation.class, new HostLocationSerializer())
99 98
100 .build(); 99 .build();
......