/** * Creates the serialized value of the object and stores this in ZooKeeper under the path. It * updates the lastStatusVersion. It does not set a watcher for the path. */ private void updateCoordinateData() throws CoordinateMissingException, CloudnameException { if (!started.get()) { throw new IllegalStateException("Not started."); } if (!zkClient.isConnected()) { throw new CloudnameException("No proper connection with zookeeper."); } synchronized (lastStatusVersionMonitor) { try { Stat stat = zkClient .getZookeeper() .setData( path, zkCoordinateData.snapshot().serialize().getBytes(Util.CHARSET_NAME), lastStatusVersion); LOG.fine("Updated coordinate, latest version is " + stat.getVersion()); lastStatusVersion = stat.getVersion(); } catch (KeeperException.NoNodeException e) { throw new CoordinateMissingException("Coordinate does not exist " + path); } catch (KeeperException e) { throw new CloudnameException( "ZooKeeper errror in updateCoordinateData: " + e.getMessage(), e); } catch (UnsupportedEncodingException e) { throw new CloudnameException(e); } catch (InterruptedException e) { throw new CloudnameException(e); } catch (IOException e) { throw new CloudnameException(e); } } }
@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(); }
/** * Handles event from ZooKeeper for this coordinate. * * @param event */ @Override public void process(WatchedEvent event) { LOG.info("Got an event from ZooKeeper " + event.toString()); synchronized (lastStatusVersionMonitor) { switch (event.getType()) { case None: switch (event.getState()) { case SyncConnected: break; case Disconnected: case AuthFailed: case Expired: default: // If we lost connection, we don't attempt to register another watcher as // this might be blocking forever. Parent will try to reconnect (reclaim) // later. isSynchronizedWithZooKeeper.set(false); sendEventToCoordinateListener( CoordinateListener.Event.NO_CONNECTION_TO_STORAGE, event.toString()); return; } return; case NodeDeleted: // If node is deleted, we have no node to place a new watcher so we stop watching. isSynchronizedWithZooKeeper.set(false); sendEventToCoordinateListener(CoordinateListener.Event.NOT_OWNER, event.toString()); return; case NodeDataChanged: LOG.fine("Node data changed, check versions."); boolean verifiedSynchronized = false; try { final Stat stat = zkClient.getZookeeper().exists(path, this); if (stat == null) { LOG.info("Could not stat path, setting out of synch, will retry claim"); } else { LOG.fine("Previous version is " + lastStatusVersion + " now is " + stat.getVersion()); if (stat.getVersion() != lastStatusVersion) { LOG.fine("Version mismatch, sending out of sync."); } else { verifiedSynchronized = true; } } } catch (KeeperException e) { LOG.fine( "Problems with zookeeper, sending consistencyState out of sync: " + e.getMessage()); } catch (InterruptedException e) { LOG.fine("Got interrupted: " + e.getMessage()); return; } finally { isSynchronizedWithZooKeeper.set(verifiedSynchronized); } if (verifiedSynchronized) { sendEventToCoordinateListener( CoordinateListener.Event.COORDINATE_OUT_OF_SYNC, event.toString()); } return; case NodeChildrenChanged: case NodeCreated: // This should not happen.. isSynchronizedWithZooKeeper.set(false); sendEventToCoordinateListener( CoordinateListener.Event.COORDINATE_OUT_OF_SYNC, event.toString()); return; } } }