Committed by
Ray Milkey
Fix potential race conditions in HazelcastLeadershipService
Change-Id: Iac232652155830c8e054760ea371ffb5639cf464
Showing
1 changed file
with
39 additions
and
32 deletions
... | @@ -166,8 +166,8 @@ public class HazelcastLeadershipService implements LeadershipService, | ... | @@ -166,8 +166,8 @@ public class HazelcastLeadershipService implements LeadershipService, |
166 | checkArgument(path != null); | 166 | checkArgument(path != null); |
167 | Topic topic = topics.get(path); | 167 | Topic topic = topics.get(path); |
168 | if (topic != null) { | 168 | if (topic != null) { |
169 | - topic.stop(); | ||
170 | topics.remove(path, topic); | 169 | topics.remove(path, topic); |
170 | + topic.stop(); | ||
171 | } | 171 | } |
172 | } | 172 | } |
173 | 173 | ||
... | @@ -213,6 +213,7 @@ public class HazelcastLeadershipService implements LeadershipService, | ... | @@ -213,6 +213,7 @@ public class HazelcastLeadershipService implements LeadershipService, |
213 | topic = new Topic(topicName); | 213 | topic = new Topic(topicName); |
214 | Topic oldTopic = topics.putIfAbsent(topicName, topic); | 214 | Topic oldTopic = topics.putIfAbsent(topicName, topic); |
215 | if (oldTopic == null) { | 215 | if (oldTopic == null) { |
216 | + // encountered new topic, start periodic processing | ||
216 | topic.start(); | 217 | topic.start(); |
217 | } else { | 218 | } else { |
218 | topic = oldTopic; | 219 | topic = oldTopic; |
... | @@ -285,7 +286,11 @@ public class HazelcastLeadershipService implements LeadershipService, | ... | @@ -285,7 +286,11 @@ public class HazelcastLeadershipService implements LeadershipService, |
285 | /** | 286 | /** |
286 | * Starts operation. | 287 | * Starts operation. |
287 | */ | 288 | */ |
288 | - private void start() { | 289 | + private synchronized void start() { |
290 | + if (!isShutdown) { | ||
291 | + // already running | ||
292 | + return; | ||
293 | + } | ||
289 | isShutdown = false; | 294 | isShutdown = false; |
290 | String threadPoolName = "onos-leader-election-" + topicName + "-%d"; | 295 | String threadPoolName = "onos-leader-election-" + topicName + "-%d"; |
291 | leaderElectionExecutor = Executors.newScheduledThreadPool(2, | 296 | leaderElectionExecutor = Executors.newScheduledThreadPool(2, |
... | @@ -303,13 +308,14 @@ public class HazelcastLeadershipService implements LeadershipService, | ... | @@ -303,13 +308,14 @@ public class HazelcastLeadershipService implements LeadershipService, |
303 | /** | 308 | /** |
304 | * Runs for leadership. | 309 | * Runs for leadership. |
305 | */ | 310 | */ |
306 | - private void runForLeadership() { | 311 | + private synchronized void runForLeadership() { |
307 | if (isRunningForLeadership) { | 312 | if (isRunningForLeadership) { |
308 | return; // Nothing to do: already running | 313 | return; // Nothing to do: already running |
309 | } | 314 | } |
310 | if (isShutdown) { | 315 | if (isShutdown) { |
311 | start(); | 316 | start(); |
312 | } | 317 | } |
318 | + isRunningForLeadership = true; | ||
313 | String lockHzId = "LeadershipService/" + topicName + "/lock"; | 319 | String lockHzId = "LeadershipService/" + topicName + "/lock"; |
314 | String termHzId = "LeadershipService/" + topicName + "/term"; | 320 | String termHzId = "LeadershipService/" + topicName + "/term"; |
315 | leaderLock = storeService.getHazelcastInstance().getLock(lockHzId); | 321 | leaderLock = storeService.getHazelcastInstance().getLock(lockHzId); |
... | @@ -326,7 +332,7 @@ public class HazelcastLeadershipService implements LeadershipService, | ... | @@ -326,7 +332,7 @@ public class HazelcastLeadershipService implements LeadershipService, |
326 | /** | 332 | /** |
327 | * Stops leadership election for the topic. | 333 | * Stops leadership election for the topic. |
328 | */ | 334 | */ |
329 | - private void stop() { | 335 | + private synchronized void stop() { |
330 | isShutdown = true; | 336 | isShutdown = true; |
331 | isRunningForLeadership = false; | 337 | isRunningForLeadership = false; |
332 | // getLockFuture.cancel(true); | 338 | // getLockFuture.cancel(true); |
... | @@ -454,22 +460,22 @@ public class HazelcastLeadershipService implements LeadershipService, | ... | @@ -454,22 +460,22 @@ public class HazelcastLeadershipService implements LeadershipService, |
454 | continue; | 460 | continue; |
455 | } | 461 | } |
456 | 462 | ||
457 | - synchronized (this) { | ||
458 | - // | ||
459 | - // This instance is now the leader | ||
460 | - // | ||
461 | - log.info("Leader Elected for topic {}", topicName); | ||
462 | - | ||
463 | - updateTerm(); | ||
464 | - | ||
465 | - leader = localNodeId; | ||
466 | - leadershipEvent = new LeadershipEvent( | ||
467 | - LeadershipEvent.Type.LEADER_ELECTED, | ||
468 | - new Leadership(topicName, localNodeId, myLastLeaderTerm)); | ||
469 | - leaderTopic.publish(SERIALIZER.encode(leadershipEvent)); | ||
470 | - } | ||
471 | - | ||
472 | try { | 463 | try { |
464 | + synchronized (this) { | ||
465 | + // | ||
466 | + // This instance is now the leader | ||
467 | + // | ||
468 | + log.info("Leader Elected for topic {}", topicName); | ||
469 | + | ||
470 | + updateTerm(); | ||
471 | + | ||
472 | + leader = localNodeId; | ||
473 | + leadershipEvent = new LeadershipEvent( | ||
474 | + LeadershipEvent.Type.LEADER_ELECTED, | ||
475 | + new Leadership(topicName, localNodeId, myLastLeaderTerm)); | ||
476 | + leaderTopic.publish(SERIALIZER.encode(leadershipEvent)); | ||
477 | + } | ||
478 | + | ||
473 | // Sleep forever until interrupted | 479 | // Sleep forever until interrupted |
474 | Thread.sleep(Long.MAX_VALUE); | 480 | Thread.sleep(Long.MAX_VALUE); |
475 | } catch (InterruptedException e) { | 481 | } catch (InterruptedException e) { |
... | @@ -479,23 +485,24 @@ public class HazelcastLeadershipService implements LeadershipService, | ... | @@ -479,23 +485,24 @@ public class HazelcastLeadershipService implements LeadershipService, |
479 | // | 485 | // |
480 | log.debug("Leader Interrupted for topic {}", | 486 | log.debug("Leader Interrupted for topic {}", |
481 | topicName); | 487 | topicName); |
482 | - } | ||
483 | 488 | ||
484 | - synchronized (this) { | 489 | + } finally { |
485 | - // If we reach here, we should release the leadership | 490 | + synchronized (this) { |
486 | - log.debug("Leader Lock Released for topic {}", topicName); | 491 | + // If we reach here, we should release the leadership |
487 | - if ((leader != null) && | 492 | + log.debug("Leader Lock Released for topic {}", topicName); |
488 | - leader.equals(localNodeId)) { | 493 | + if ((leader != null) && |
489 | - leader = null; | 494 | + leader.equals(localNodeId)) { |
495 | + leader = null; | ||
496 | + } | ||
497 | + leadershipEvent = new LeadershipEvent( | ||
498 | + LeadershipEvent.Type.LEADER_BOOTED, | ||
499 | + new Leadership(topicName, localNodeId, myLastLeaderTerm)); | ||
500 | + leaderTopic.publish(SERIALIZER.encode(leadershipEvent)); | ||
501 | + leaderLock.unlock(); | ||
490 | } | 502 | } |
491 | - leadershipEvent = new LeadershipEvent( | ||
492 | - LeadershipEvent.Type.LEADER_BOOTED, | ||
493 | - new Leadership(topicName, localNodeId, myLastLeaderTerm)); | ||
494 | - leaderTopic.publish(SERIALIZER.encode(leadershipEvent)); | ||
495 | - leaderLock.unlock(); | ||
496 | } | 503 | } |
497 | } | 504 | } |
498 | - | 505 | + isRunningForLeadership = false; |
499 | } | 506 | } |
500 | 507 | ||
501 | // Globally guarded by the leadership lock for this term | 508 | // Globally guarded by the leadership lock for this term | ... | ... |
-
Please register or login to post a comment