@Override public void run() { if (isSynchronizedWithZooKeeper.get() || !zkClient.isConnected() || !started.get()) { return; } if (checkVersion.getAndSet(false)) { try { synchronized (lastStatusVersionMonitor) { final Stat stat = zkClient.getZookeeper().exists(path, null); if (stat != null && zkClient.getZookeeper().getSessionId() == stat.getEphemeralOwner()) { zkClient.getZookeeper().delete(path, lastStatusVersion); } } } catch (InterruptedException e) { LOG.info("Interrupted"); checkVersion.set(true); } catch (KeeperException e) { LOG.info("exception " + e.getMessage()); checkVersion.set(true); } } LOG.info( "We are out-of-sync, have a zookeeper connection, and are started, trying reclaim: " + path + this); tryClaim(); }
@Override public void processResult(int rawReturnCode, String notUsed, Object parent, String notUsed2) { KeeperException.Code returnCode = KeeperException.Code.get(rawReturnCode); ClaimedCoordinate claimedCoordinate = (ClaimedCoordinate) parent; LOG.fine( "Claim callback with " + returnCode.name() + " " + claimedCoordinate.path + " synched: " + isSynchronizedWithZooKeeper.get() + " thread: " + this); switch (returnCode) { // The claim was successful. This means that the node was created. We need to // populate the status and endpoints. case OK: // We should be the first one to write to the new node, or fail. // This requires that the first version is 0, have not seen this documented // but it should be a fair assumption and is verified by unit tests. synchronized (lastStatusVersionMonitor) { lastStatusVersion = 0; } // We need to set this to synced or updateCoordinateData will complain. // updateCoordinateData will set it to out-of-sync in case of problems. isSynchronizedWithZooKeeper.set(true); try { registerWatcher(); } catch (CloudnameException e) { LOG.fine( "Failed register watcher after claim. Going to state out of sync: " + e.getMessage()); isSynchronizedWithZooKeeper.set(false); return; } catch (InterruptedException e) { LOG.fine("Interrupted while setting up new watcher. Going to state out of sync."); isSynchronizedWithZooKeeper.set(false); return; } // No exceptions, let's celebrate with a log message. LOG.info("Claim processed ok, path: " + path); claimedCoordinate.sendEventToCoordinateListener( CoordinateListener.Event.COORDINATE_OK, "claimed"); return; case NODEEXISTS: // Someone has already claimed the coordinate. It might have been us in a // different thread. If we already have claimed the coordinate then don't care. // Else notify the client. If everything is fine, this is not a true negative, // so ignore it. It might happen if two attempts to tryClaim the coordinate run // in parallel. if (isSynchronizedWithZooKeeper.get() && started.get()) { LOG.fine("Everything is fine, ignoring NODEEXISTS message, path: " + path); return; } LOG.info("Claimed fail, node already exists, will retry: " + path); claimedCoordinate.sendEventToCoordinateListener( CoordinateListener.Event.NOT_OWNER, "Node already exists."); LOG.info("isSynchronizedWithZooKeeper: " + isSynchronizedWithZooKeeper.get()); checkVersion.set(true); return; case NONODE: LOG.info("Could not claim due to missing coordinate, path: " + path); claimedCoordinate.sendEventToCoordinateListener( CoordinateListener.Event.NOT_OWNER, "No node on claiming coordinate: " + returnCode.name()); return; default: // Random problem, report the problem to the client. claimedCoordinate.sendEventToCoordinateListener( CoordinateListener.Event.NO_CONNECTION_TO_STORAGE, "Could not reclaim coordinate. Return code: " + returnCode.name()); return; } }