private void handleStateChange(ConnectionState newState) { switch (newState) { default: { // NOP break; } case RECONNECTED: { try { reset(); } catch (Exception e) { log.error("Could not reset leader latch", e); setLeadership(false); } break; } case SUSPENDED: case LOST: { setLeadership(false); break; } } }
@VisibleForTesting void reset() throws Exception { setLeadership(false); setNode(null); BackgroundCallback callback = new BackgroundCallback() { @Override public void processResult(CuratorFramework client, CuratorEvent event) throws Exception { if (debugResetWaitLatch != null) { debugResetWaitLatch.await(); debugResetWaitLatch = null; } if (event.getResultCode() == KeeperException.Code.OK.intValue()) { setNode(event.getName()); getChildren(); } else { log.error("getChildren() failed. rc = " + event.getResultCode()); } } }; client .create() .creatingParentsIfNeeded() .withProtection() .withMode(CreateMode.EPHEMERAL_SEQUENTIAL) .inBackground(callback) .forPath(ZKPaths.makePath(latchPath, LOCK_NAME), LeaderSelector.getIdBytes(id)); }
/** * Remove this instance from the leadership election. If this instance is the leader, leadership * is released. IMPORTANT: the only way to release leadership is by calling close(). All * LeaderLatch instances must eventually be closed. * * @throws IOException errors */ @Override public void close() throws IOException { Preconditions.checkState(state.compareAndSet(State.STARTED, State.CLOSED), "Not started"); try { client.delete().guaranteed().inBackground().forPath(ourPath); } catch (Exception e) { throw new IOException(e); } finally { client.getConnectionStateListenable().removeListener(listener); setLeadership(false); } }
/** * Remove this instance from the leadership election. If this instance is the leader, leadership * is released. IMPORTANT: the only way to release leadership is by calling close(). All * LeaderLatch instances must eventually be closed. * * @throws IOException errors */ @Override public void close() throws IOException { Preconditions.checkState( state.compareAndSet(State.STARTED, State.CLOSED), "Already closed or has not been started"); try { setNode(null); } catch (Exception e) { throw new IOException(e); } finally { client.getConnectionStateListenable().removeListener(listener); setLeadership(false); } }
private void handleStateChange(ConnectionState newState) { if (newState == ConnectionState.RECONNECTED) { newState = ConnectionState.CONNECTED; } ConnectionState previousState = connectionState.getAndSet(newState); if ((previousState == ConnectionState.LOST) && (newState == ConnectionState.CONNECTED)) { try { internalStart(); } catch (Exception e) { log.error("Could not restart leader latch", e); connectionState.set(ConnectionState.LOST); setLeadership(false); } } }
private void checkLeadership(List<String> children) throws Exception { final String localOurPath = ourPath.get(); List<String> sortedChildren = LockInternals.getSortedChildren(LOCK_NAME, sorter, children); int ourIndex = (localOurPath != null) ? sortedChildren.indexOf(ZKPaths.getNodeFromPath(localOurPath)) : -1; if (ourIndex < 0) { log.error("Can't find our node. Resetting. Index: " + ourIndex); reset(); } else if (ourIndex == 0) { setLeadership(true); } else { String watchPath = sortedChildren.get(ourIndex - 1); Watcher watcher = new Watcher() { @Override public void process(WatchedEvent event) { if ((state.get() == State.STARTED) && (event.getType() == Event.EventType.NodeDeleted) && (localOurPath != null)) { try { getChildren(); } catch (Exception ex) { log.error("An error occurred checking the leadership.", ex); } } } }; BackgroundCallback callback = new BackgroundCallback() { @Override public void processResult(CuratorFramework client, CuratorEvent event) throws Exception { if (event.getResultCode() == KeeperException.Code.NONODE.intValue()) { // previous node is gone - reset reset(); } } }; client .checkExists() .usingWatcher(watcher) .inBackground(callback) .forPath(ZKPaths.makePath(latchPath, watchPath)); } }
private void checkForLeadership() throws Exception { List<String> sortedChildren = LockInternals.getSortedChildren(client, latchPath, LOCK_NAME, sorter); if (sortedChildren.size() == 0) { throw new Exception("no children - unexpected state"); } int ourIndex = sortedChildren.indexOf(ZKPaths.getNodeFromPath(ourPath)); if (ourIndex == 0) { setLeadership(true); } else { final String ourPathWhenWatched = ourPath; // protected against a lost/suspended connection and an old watcher - I'm not // sure if this is possible but it can't hurt String watchPath = sortedChildren.get(ourIndex - 1); Watcher watcher = new Watcher() { @Override public void process(WatchedEvent event) { if ((event.getType() == Event.EventType.NodeDeleted) && (ourPath != null) && ourPath.equals(ourPathWhenWatched)) { try { checkForLeadership(); } catch (Exception ex) { log.error("An error ocurred checking the leadership.", ex); } } } }; if (client.checkExists().usingWatcher(watcher).forPath(ZKPaths.makePath(latchPath, watchPath)) == null) { // the previous Participant may be down, so we need to reevaluate the list // to get the actual previous Participant or get the leadership checkForLeadership(); } } }