|
From: Benjamin R. <br...@ya...> - 2008-07-14 15:22:55
|
The easiest way to fix this code is to move the Collections.sort(values) to
right after the zk.getChildren() and then use the following Comparator with
Collections.sort() and Collections.binarySearch():
/* This Comparator defines an ordering such that the strings with
* the lowest sequence numbers are first in sequence sorted order
* followed by strings without sequence numbers in lexographical
* order. This class assumes that a '-' preceeds the sequence
* number. */
class SequenceComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
int s1 = getSequence(o1);
int s2 = getSequence(o2);
if (s1 == -1 && s2 == -1) {
return o1.compareTo(o2);
}
return s1 == -1 ? 1 : s2 == -1 ? -1 : s1 - s2 ? : -1;
}
/* Returns the sequence suffix of s. This method assumes that
* the sequence number is prefixed with a '-'. */
private int getSequence(String s) {
int i = s.lastIndexOf('-');
if (i != -1) {
try {
return Integer.parseInt(s.substring(i+1));
// If an exception occurred we misdetected a sequence suffix,
// so return -1.
} catch(NumberFormatException e) {
} catch(ArrayIndexOutOfBoundsException e) {
}
}
return -1;
}
}
ben
On Thursday 10 July 2008 22:20:06 Avinash Lakshman wrote:
> Hi
>
> I am trying to elect leader among 50 nodes. There is always one odd guy who
> seems to think that someone else distinct from what some other nodes see as
> leader. Could someone please tell me what is wrong with the following code
> for leader election:
>
> public void electLeader()
> {
> ZooKeeper zk = StorageService.instance().getZooKeeperHandle();
> String path = "/Leader";
> try
> {
> String createPath = path +
> "/L-";
> LeaderElector.createLock_.lock();
> while( true )
> {
> /* Get all znodes under the Leader znode */
> List<String> values = zk.getChildren(path, false);
> /*
> * Get the first znode and if it is the
> * pathCreated created above then the data
> * in that znode is the leader's identity.
> */
> if ( leader_ == null )
> {
> leader_ = new AtomicReference<EndPoint>(
> EndPoint.fromBytes( zk.getData(path + "/" + values.get(0), false, null) )
> ); }
> else
> {
> leader_.set( EndPoint.fromBytes( zk.getData(path +
> "/" + values .get(0), false, null) ) );
> /* Disseminate the state as to who the leader is.
> */ onLeaderElection();
> }
> logger_.debug("Elected leader is " + leader_ + " @
> znode " + ( path + "/" + values.get(0) ) );
> Collections.sort(values);
> /* We need only the last portion of this znode */
> String[] peices = pathCreated_.split("/");
> int index = Collections.binarySearch(values,
> peices[peices.length - 1]);
> if ( index > 0 )
> {
> String pathToCheck = path + "/" + values.get(index
> - 1);
> Stat stat = zk.exists(pathToCheck, true);
> if ( stat != null )
> {
> logger_.debug("Awaiting my turn ...");
> condition_.await();
> logger_.debug("Checking to see if leader is
> around ...");
> }
> }
> else
> {
> break;
> }
> }
> }
> catch ( InterruptedException ex )
> {
> logger_.warn(LogUtil.throwableToString(ex));
> }
> catch ( KeeperException ex )
> {
> logger_.warn(LogUtil.throwableToString(ex));
> }
> finally
> {
> LeaderElector.createLock_.unlock();
> }
> }
> }
>
> Thanks
> Avinash
|