package com.neverwinterdp.registry.election; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import com.neverwinterdp.registry.ErrorCode; import com.neverwinterdp.registry.Node; import com.neverwinterdp.registry.NodeCreateMode; import com.neverwinterdp.registry.Registry; import com.neverwinterdp.registry.RegistryException; import com.neverwinterdp.registry.event.NodeEvent; import com.neverwinterdp.registry.event.NodeWatcher; import com.neverwinterdp.util.JSONSerializer; public class LeaderElection { private Registry registry ; private String electionPath ; private LeaderId leaderId ; private LeaderElectionListener listener ; private boolean elected = false ; private Node node ; private byte[] info = {}; public LeaderElection(Registry registry, String electionPath) { this.registry = registry; this.electionPath = electionPath ; } public <T> LeaderElection(Registry registry, String electionPath, byte[] info) { this(registry, electionPath); this.info = info; } public <T> LeaderElection(Registry registry, String electionPath, T info) { this(registry, electionPath); this.info = JSONSerializer.INSTANCE.toBytes(info); } public Registry getRegistry() { return this.registry ; } public String getElectionPath() { return this.electionPath ; } public void setListener(LeaderElectionListener listener) { this.listener = listener ; } public boolean isElected() { return this.elected ; } public LeaderId getLeaderId() { return this.leaderId ; } public Node getNode() { return this.node; } public void start() throws RegistryException { if(leaderId != null) { throw new RegistryException(ErrorCode.Unknown, "This leader election is already started") ; } String lockPath = electionPath + "/leader-" ; node = registry.create(lockPath , info, NodeCreateMode.EPHEMERAL_SEQUENTIAL); leaderId = new LeaderId(node.getPath()) ; LeaderWatcher watcher = new LeaderWatcher() ; watcher.watch(); } public void stop() throws RegistryException { registry.delete(leaderId.getPath()); elected = false ; leaderId = null ; node = null ; } private SortedSet<LeaderId> getSortedLockIds() throws RegistryException { List<String> names = registry.getChildren(electionPath) ; SortedSet<LeaderId> sortedLockIds = new TreeSet<LeaderId>(); for (String nodeName : names) { if(nodeName.startsWith("leader-")) { sortedLockIds.add(new LeaderId(electionPath + "/" + nodeName)); } } return sortedLockIds; } class LeaderWatcher extends NodeWatcher { @Override public void onEvent(NodeEvent event) { try { System.err.println("Election event: path = " + event.getType() + ", type" + event.getType()); watch() ; } catch(RegistryException ex) { throw new RuntimeException(ex) ; } } public void watch() throws RegistryException { SortedSet<LeaderId> leaderIds = getSortedLockIds() ; LeaderId ownerId = leaderIds.first() ; if(ownerId.equals(leaderId)) { listener.onElected(); elected = true ; return ; } SortedSet<LeaderId> lessThanMe = leaderIds.headSet(leaderId); LeaderId previousLock = lessThanMe.last(); registry.watchExists(previousLock.getPath(), this); } } }