├── zoodb ├── server1 │ └── myid ├── server2 │ └── myid └── server3 │ └── myid ├── lib ├── log4j-1.2.16.jar └── zookeeper-3.3.1.jar ├── config ├── zoo1.cfg ├── zoo2.cfg └── zoo3.cfg ├── src ├── server │ ├── ZooKeeperServerTwo.java │ ├── ZooKeeperServerThree.java │ └── ZooKeeperServerOne.java └── client │ ├── ZooKeeperClientTwo.java │ ├── ZooKeeperClientThree.java │ └── ZooKeeperClientOne.java └── README.markdown /zoodb/server1/myid: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /zoodb/server2/myid: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /zoodb/server3/myid: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /lib/log4j-1.2.16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlricQin/zookeeper-leader-election/master/lib/log4j-1.2.16.jar -------------------------------------------------------------------------------- /lib/zookeeper-3.3.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlricQin/zookeeper-leader-election/master/lib/zookeeper-3.3.1.jar -------------------------------------------------------------------------------- /config/zoo1.cfg: -------------------------------------------------------------------------------- 1 | tickTime=2000 2 | dataDir=zoodb/server1 3 | clientPort=2181 4 | initLimit=5 5 | syncLimit=2 6 | server.1=localhost:2888:3888 7 | server.2=localhost:2889:3889 8 | server.3=localhost:2890:3890 9 | -------------------------------------------------------------------------------- /config/zoo2.cfg: -------------------------------------------------------------------------------- 1 | tickTime=2000 2 | dataDir=zoodb/server2 3 | clientPort=2182 4 | initLimit=5 5 | syncLimit=2 6 | server.1=localhost:2888:3888 7 | server.2=localhost:2889:3889 8 | server.3=localhost:2890:3890 9 | -------------------------------------------------------------------------------- /config/zoo3.cfg: -------------------------------------------------------------------------------- 1 | tickTime=2000 2 | dataDir=zoodb/server3 3 | clientPort=2183 4 | initLimit=5 5 | syncLimit=2 6 | server.1=localhost:2888:3888 7 | server.2=localhost:2889:3889 8 | server.3=localhost:2890:3890 9 | -------------------------------------------------------------------------------- /src/server/ZooKeeperServerTwo.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.zookeeper.server.ServerConfig; 6 | import org.apache.zookeeper.server.ZooKeeperServerMain; 7 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig; 8 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException; 9 | 10 | public class ZooKeeperServerTwo { 11 | 12 | /******************************************************************************* 13 | * RUN SERVER TWO 14 | ******************************************************************************/ 15 | public static void main(String[] args){ 16 | 17 | ZooKeeperServerMain zkserver = new ZooKeeperServerMain(); 18 | ServerConfig sc = new ServerConfig(); 19 | QuorumPeerConfig qpc = new QuorumPeerConfig(); 20 | 21 | try { 22 | qpc.parse("conf/zoo2.cfg"); 23 | } catch (ConfigException e) { 24 | e.printStackTrace(); 25 | } 26 | 27 | sc.readFrom(qpc); 28 | 29 | System.out.println("SERVER TWO :: STARTED\n"); 30 | 31 | try { 32 | zkserver.runFromConfig(sc); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | 37 | System.out.println("SERVER TWO :: AFTER runFromConfig =O\n"); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/server/ZooKeeperServerThree.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.zookeeper.server.ServerConfig; 6 | import org.apache.zookeeper.server.ZooKeeperServerMain; 7 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig; 8 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException; 9 | 10 | public class ZooKeeperServerThree { 11 | 12 | /******************************************************************************* 13 | * RUN SERVER THREE 14 | ******************************************************************************/ 15 | public static void main(String[] args){ 16 | 17 | ZooKeeperServerMain zkserver = new ZooKeeperServerMain(); 18 | ServerConfig sc = new ServerConfig(); 19 | QuorumPeerConfig qpc = new QuorumPeerConfig(); 20 | 21 | try { 22 | qpc.parse("conf/zoo3.cfg"); 23 | } catch (ConfigException e) { 24 | e.printStackTrace(); 25 | } 26 | 27 | sc.readFrom(qpc); 28 | 29 | System.out.println("SERVER THREE :: STARTED\n"); 30 | 31 | try { 32 | zkserver.runFromConfig(sc); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | 37 | System.out.println("SERVER THREE :: AFTER runFromConfig =O\n"); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/server/ZooKeeperServerOne.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.zookeeper.server.ServerConfig; 6 | import org.apache.zookeeper.server.ZooKeeperServerMain; 7 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig; 8 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException; 9 | 10 | public class ZooKeeperServerOne { 11 | 12 | /******************************************************************************* 13 | * RUN SERVER ONE 14 | ******************************************************************************/ 15 | public static void main(String[] args){ 16 | 17 | ZooKeeperServerMain zkserver = new ZooKeeperServerMain(); 18 | ServerConfig sc = new ServerConfig(); 19 | QuorumPeerConfig qpc = new QuorumPeerConfig(); 20 | 21 | try { 22 | qpc.parse("conf/zoo1.cfg"); 23 | } catch (ConfigException e) { 24 | e.printStackTrace(); 25 | } 26 | 27 | sc.readFrom(qpc); 28 | 29 | System.out.println("SERVER ONE :: STARTED\n"); 30 | 31 | try { 32 | zkserver.runFromConfig(sc); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | 37 | System.out.println("SERVER ONE :: AFTER runFromConfig. Something is very wrong.\n"); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ZooKeeper Leader Election 2 | ======================== 3 | 4 | To complete my M.S.c in Informatics Engineering at Lisbon University, I was part of the Navigators research team [(navigators.di.fc.ul.pt](http://navigators.di.fc.ul.pt)). The investigation project was ReD ([http://red.lsd.di.uminho.pt](http://red.lsd.di.uminho.pt)) and my thesis consists of Coordination Services for Replicated Databases. 5 | 6 | To achive my goals, I implemented a leader election service with the help of ZooKeeper, based on one of it recipes ([http://zookeeper.apache.org/doc/trunk/recipes.html](http://zookeeper.apache.org/doc/trunk/recipes.html)). 7 | 8 | ZooKeeper 9 | --------- 10 | 11 | ZooKeeper is a service for coordinating processes of distributed applications. It is often a part of critical infrastructure and it aims to provide a simple and high performance kernel for building complex coordination primitives. 12 | 13 | See also: [Apache ZooKeeper](http://zookeeper.apache.org/) 14 | 15 | Instructions 16 | ------------ 17 | 18 | 1. 19 | Edit files `/config/zoo1.cfg`, `zoo2.cfg` and `zoo3.cfg`. Locate the line `dataDir=zoodb/server**X**`. Replace `zoodb/server**X**` with the full path to the corresponding "database" folders. In my example that would be `zoodb/server1`, `zoodb/server2` and `zoodb/server3`. 20 | 21 | 2. 22 | Locate the classes `zookeeper.server.ZooKeeperServerOne`, `ZooKeeperServerTwo`, `ZooKeeperServerThree`. At line 22: `qpc.parse("config/zoo1.cfg");` replace `config/zoo1.cfg` with full path for each `zooX.cfg` file. 23 | 24 | 3. 25 | Initialize ZooKeeper servers: `java -cp bin/:lib/log4j-1.2.16.jar:lib/zookeeper-3.3.1.jar zookeeper.server.ZooKeeperServerOne` or `./zkserver`. Note: It is possible to run ZooKeeper with only one server, but if you want you can also start `ZooKeeperServerTwo` and/or `ZooKeeperServerThree`. 26 | 27 | That's it. You now have a running ZooKeeper server, ready to receive requests. 28 | 29 | Contact 30 | ------- 31 | 32 | Please, feel free to contact me with any question at: 33 | 34 | [@ruiposse](https://twitter.com/#!/ruiposse) 35 | 36 | ruiposse [at] gmail [dot] com 37 | 38 |
39 | 40 | ###### © Rui Posse 2011. ###### -------------------------------------------------------------------------------- /src/client/ZooKeeperClientTwo.java: -------------------------------------------------------------------------------- 1 | package client; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | import org.apache.zookeeper.CreateMode; 7 | import org.apache.zookeeper.KeeperException; 8 | import org.apache.zookeeper.WatchedEvent; 9 | import org.apache.zookeeper.Watcher; 10 | import org.apache.zookeeper.ZooKeeper; 11 | import org.apache.zookeeper.ZooDefs.Ids; 12 | import org.apache.zookeeper.data.Stat; 13 | 14 | public class ZooKeeperClientTwo implements Watcher { 15 | 16 | private ZooKeeper zk; 17 | 18 | private final String PATH = "/election"; 19 | 20 | public ZooKeeperClientTwo() throws IOException, KeeperException, InterruptedException{ 21 | 22 | /******************** 23 | * STARTING ZOOKEEPER 24 | ********************/ 25 | System.out.println("CLIENT TWO :: STARTING\n"); 26 | zk = new ZooKeeper("127.0.0.1", 3000, this); 27 | System.out.println("CLIENT TWO :: FINISHED STARTING\n"); 28 | 29 | // Leader Election 30 | leaderElection(); 31 | 32 | int pause = new Scanner(System.in).nextInt(); 33 | } 34 | 35 | /** 36 | * Leader Election 37 | * @throws InterruptedException 38 | * @throws KeeperException 39 | */ 40 | public void leaderElection() throws KeeperException, InterruptedException{ 41 | 42 | // If is the first client, then it should create the znode "/election" 43 | Stat stat = zk.exists(PATH, false); 44 | if(stat == null){ 45 | System.out.println("CLIENT TWO :: Im the first client, creating " + PATH + "."); 46 | String election = "/election"; 47 | String r = zk.create(election, new byte[0], Ids.OPEN_ACL_UNSAFE, 48 | CreateMode.PERSISTENT); 49 | System.out.println("CLIENT TWO :: " + r + " created."); 50 | } 51 | 52 | // Create znode z with path "ELECTION/n_" with both SEQUENCE and EPHEMERAL flags 53 | String childPath = PATH + "/n_"; 54 | 55 | childPath = zk.create(childPath, new byte[0], Ids.OPEN_ACL_UNSAFE, 56 | CreateMode.EPHEMERAL_SEQUENTIAL); 57 | System.out.println("CLIENT TWO :: My leader proposal created. Path = " + childPath + "."); 58 | 59 | // Let C be the children of "ELECTION", and i be the sequence number of z; 60 | // Watch for changes on "ELECTION/n_j", where j is the smallest sequence 61 | // number such that j < i and n_j is a znode in C; 62 | List children = zk.getChildren(PATH, false); 63 | 64 | String tmp = children.get(0); 65 | 66 | for(String s : children){ 67 | if(tmp.compareTo(s) > 0) 68 | tmp = s; 69 | } 70 | 71 | // i contains the smallest sequence number 72 | String leader = PATH + "/" + tmp; 73 | Stat s = zk.exists(leader, true); 74 | 75 | 76 | // syso 77 | System.out.println("CLIENT TWO :: Leader is the owner of znode: " + leader); 78 | System.out.println("CLIENT ONE :: Leader id: " + s.getEphemeralOwner()); 79 | } 80 | 81 | public void newLeaderElection() throws KeeperException, InterruptedException{ 82 | 83 | List children = zk.getChildren(PATH, false); 84 | 85 | String tmp = children.get(0); 86 | 87 | for(String s : children){ 88 | if(tmp.compareTo(s) > 0) 89 | tmp = s; 90 | } 91 | 92 | // i contains the smallest sequence number 93 | String leader = PATH + "/" + tmp; 94 | Stat s = zk.exists(leader, true); 95 | 96 | // syso 97 | System.out.println("CLIENT TWO :: Leader is the owner of znode: " + leader); 98 | System.out.println("CLIENT ONE :: Leader id: " + s.getEphemeralOwner()); 99 | } 100 | 101 | 102 | @Override 103 | public void process(WatchedEvent event) { 104 | 105 | switch (event.getType()){ 106 | 107 | case NodeChildrenChanged: 108 | System.out.println("CLIENT TWO :: NodeChildrenChanged | ZNode: " + event.getPath()); 109 | break; 110 | 111 | case NodeCreated: 112 | System.out.println("CLIENT TWO :: NodeCreated | ZNode: " + event.getPath()); 113 | break; 114 | 115 | case NodeDataChanged: 116 | System.out.println("CLIENT TWO :: NodeDataChanged | ZNode: " + event.getPath()); 117 | break; 118 | 119 | case NodeDeleted: 120 | System.out.println("CLIENT TWO :: NodeDeleted | ZNode: " + event.getPath()); 121 | System.out.println("CLIENT TWO :: Leader was lost, newLeaderElection started."); 122 | try { 123 | newLeaderElection(); 124 | } catch (KeeperException e) { 125 | e.printStackTrace(); 126 | } catch (InterruptedException e) { 127 | e.printStackTrace(); 128 | } 129 | break; 130 | 131 | case None: 132 | 133 | switch (event.getState()){ 134 | 135 | case Disconnected: 136 | break; 137 | 138 | case Expired: 139 | break; 140 | 141 | case NoSyncConnected: 142 | System.out.println("CLIENT TWO :: NoSyncConnected - Deprecated"); 143 | break; 144 | 145 | case SyncConnected: 146 | break; 147 | 148 | case Unknown: 149 | System.out.println("CLIENT TWO :: Unknown - Deprecated"); 150 | break; 151 | } 152 | } 153 | } 154 | 155 | 156 | public static void main (String[] args){ 157 | try { 158 | new ZooKeeperClientTwo(); 159 | } catch (KeeperException e) { 160 | e.printStackTrace(); 161 | } catch (InterruptedException e) { 162 | e.printStackTrace(); 163 | } catch (IOException e) { 164 | e.printStackTrace(); 165 | } 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /src/client/ZooKeeperClientThree.java: -------------------------------------------------------------------------------- 1 | package client; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | import org.apache.zookeeper.CreateMode; 7 | import org.apache.zookeeper.KeeperException; 8 | import org.apache.zookeeper.WatchedEvent; 9 | import org.apache.zookeeper.Watcher; 10 | import org.apache.zookeeper.ZooKeeper; 11 | import org.apache.zookeeper.ZooDefs.Ids; 12 | import org.apache.zookeeper.data.Stat; 13 | 14 | public class ZooKeeperClientThree implements Watcher { 15 | 16 | private ZooKeeper zk; 17 | 18 | private final String PATH = "/election"; 19 | 20 | public ZooKeeperClientThree() throws IOException, KeeperException, InterruptedException{ 21 | 22 | /******************** 23 | * STARTING ZOOKEEPER 24 | ********************/ 25 | System.out.println("CLIENT THREE :: STARTING\n"); 26 | zk = new ZooKeeper("127.0.0.1", 3000, this); 27 | System.out.println("CLIENT THREE :: FINISHED STARTING\n"); 28 | 29 | // Leader Election 30 | leaderElection(); 31 | 32 | int pause = new Scanner(System.in).nextInt(); 33 | } 34 | 35 | /** 36 | * Leader Election 37 | * @throws InterruptedException 38 | * @throws KeeperException 39 | */ 40 | public void leaderElection() throws KeeperException, InterruptedException{ 41 | 42 | // If is the first client, then it should create the znode "/election" 43 | Stat stat = zk.exists(PATH, false); 44 | if(stat == null){ 45 | System.out.println("CLIENT THREE :: Im the first client, creating " + PATH + "."); 46 | String election = "/election"; 47 | String r = zk.create(election, new byte[0], Ids.OPEN_ACL_UNSAFE, 48 | CreateMode.PERSISTENT); 49 | System.out.println("CLIENT THREE :: " + r + " created."); 50 | } 51 | 52 | // Create znode z with path "ELECTION/n_" with both SEQUENCE and EPHEMERAL flags 53 | String childPath = PATH + "/n_"; 54 | 55 | childPath = zk.create(childPath, new byte[0], Ids.OPEN_ACL_UNSAFE, 56 | CreateMode.EPHEMERAL_SEQUENTIAL); 57 | System.out.println("CLIENT THREE :: My leader proposal created. Path = " + childPath + "."); 58 | 59 | // Let C be the children of "ELECTION", and i be the sequence number of z; 60 | // Watch for changes on "ELECTION/n_j", where j is the smallest sequence 61 | // number such that j < i and n_j is a znode in C; 62 | List children = zk.getChildren(PATH, false); 63 | 64 | String tmp = children.get(0); 65 | 66 | for(String s : children){ 67 | if(tmp.compareTo(s) > 0) 68 | tmp = s; 69 | } 70 | 71 | // i contains the smallest sequence number 72 | String leader = PATH + "/" + tmp; 73 | Stat s = zk.exists(leader, true); 74 | 75 | // syso 76 | System.out.println("CLIENT THREE :: Leader is the owner of znode: " + leader); 77 | System.out.println("CLIENT ONE :: Leader id: " + s.getEphemeralOwner()); 78 | } 79 | 80 | public void newLeaderElection() throws KeeperException, InterruptedException{ 81 | 82 | List children = zk.getChildren(PATH, false); 83 | 84 | String tmp = children.get(0); 85 | 86 | for(String s : children){ 87 | if(tmp.compareTo(s) > 0) 88 | tmp = s; 89 | } 90 | 91 | // i contains the smallest sequence number 92 | String leader = PATH + "/" + tmp; 93 | Stat s = zk.exists(leader, true); 94 | 95 | // syso 96 | System.out.println("CLIENT THREE :: Leader is the owner of znode: " + leader); 97 | System.out.println("CLIENT ONE :: Leader id: " + s.getEphemeralOwner()); 98 | } 99 | 100 | 101 | @Override 102 | public void process(WatchedEvent event) { 103 | 104 | switch (event.getType()){ 105 | 106 | case NodeChildrenChanged: 107 | System.out.println("CLIENT THREE :: NodeChildrenChanged | ZNode: " + event.getPath()); 108 | break; 109 | 110 | case NodeCreated: 111 | System.out.println("CLIENT THREE :: NodeCreated | ZNode: " + event.getPath()); 112 | break; 113 | 114 | case NodeDataChanged: 115 | System.out.println("CLIENT THREE :: NodeDataChanged | ZNode: " + event.getPath()); 116 | break; 117 | 118 | case NodeDeleted: 119 | System.out.println("CLIENT THREE :: NodeDeleted | ZNode: " + event.getPath()); 120 | System.out.println("CLIENT THREE :: Leader was lost, newLeaderElection started."); 121 | try { 122 | newLeaderElection(); 123 | } catch (KeeperException e) { 124 | e.printStackTrace(); 125 | } catch (InterruptedException e) { 126 | e.printStackTrace(); 127 | } 128 | break; 129 | 130 | case None: 131 | 132 | switch (event.getState()){ 133 | 134 | case Disconnected: 135 | break; 136 | 137 | case Expired: 138 | break; 139 | 140 | case NoSyncConnected: 141 | System.out.println("CLIENT THREE :: NoSyncConnected - Deprecated"); 142 | break; 143 | 144 | case SyncConnected: 145 | break; 146 | 147 | case Unknown: 148 | System.out.println("CLIENT THREE :: Unknown - Deprecated"); 149 | break; 150 | } 151 | } 152 | } 153 | 154 | 155 | public static void main (String[] args){ 156 | try { 157 | new ZooKeeperClientThree(); 158 | } catch (KeeperException e) { 159 | e.printStackTrace(); 160 | } catch (InterruptedException e) { 161 | e.printStackTrace(); 162 | } catch (IOException e) { 163 | e.printStackTrace(); 164 | } 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/client/ZooKeeperClientOne.java: -------------------------------------------------------------------------------- 1 | package client; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | import org.apache.zookeeper.CreateMode; 7 | import org.apache.zookeeper.KeeperException; 8 | import org.apache.zookeeper.WatchedEvent; 9 | import org.apache.zookeeper.Watcher; 10 | import org.apache.zookeeper.ZooKeeper; 11 | import org.apache.zookeeper.ZooDefs.Ids; 12 | import org.apache.zookeeper.data.Stat; 13 | 14 | public class ZooKeeperClientOne implements Watcher { 15 | 16 | private ZooKeeper zk; 17 | 18 | private final String PATH = "/election"; 19 | 20 | public ZooKeeperClientOne() throws IOException, KeeperException, InterruptedException{ 21 | 22 | /******************** 23 | * STARTING ZOOKEEPER 24 | ********************/ 25 | System.out.println("CLIENT ONE :: STARTING\n"); 26 | zk = new ZooKeeper("127.0.0.1", 3000, this); 27 | System.out.println("CLIENT ONE :: FINISHED STARTING\n"); 28 | 29 | // Leader Election 30 | leaderElection(); 31 | 32 | int pause = new Scanner(System.in).nextInt(); 33 | } 34 | 35 | /** 36 | * Leader Election 37 | * @throws InterruptedException 38 | * @throws KeeperException 39 | */ 40 | public void leaderElection() throws KeeperException, InterruptedException{ 41 | 42 | // If is the first client, then it should create the znode "/election" 43 | Stat stat = zk.exists(PATH, false); 44 | if(stat == null){ 45 | System.out.println("CLIENT ONE :: Im the first client, creating " + PATH + "."); 46 | String election = "/election"; 47 | String r = zk.create(election, new byte[0], Ids.OPEN_ACL_UNSAFE, 48 | CreateMode.PERSISTENT); 49 | System.out.println("CLIENT ONE :: " + r + " created."); 50 | } 51 | 52 | // Create znode z with path "ELECTION/n_" with both SEQUENCE and EPHEMERAL flags 53 | String childPath = PATH + "/n_"; 54 | 55 | childPath = zk.create(childPath, new byte[0], Ids.OPEN_ACL_UNSAFE, 56 | CreateMode.EPHEMERAL_SEQUENTIAL); 57 | System.out.println("CLIENT ONE :: My leader proposal created. Path = " + childPath + "."); 58 | 59 | // Let C be the children of "ELECTION", and i be the sequence number of z; 60 | // Watch for changes on "ELECTION/n_j", where j is the smallest sequence 61 | // number such that j < i and n_j is a znode in C; 62 | List children = zk.getChildren(PATH, false); 63 | 64 | String tmp = children.get(0); 65 | 66 | for(String s : children){ 67 | if(tmp.compareTo(s) > 0) 68 | tmp = s; 69 | } 70 | 71 | // i contains the smallest sequence number 72 | //String leader = PATH + "/n_" + i; 73 | String leader = PATH + "/" + tmp; 74 | Stat s = zk.exists(leader, true); 75 | 76 | // syso 77 | System.out.println("CLIENT ONE :: Leader is the owner of znode: " + leader); 78 | System.out.println("CLIENT ONE :: Leader id: " + s.getEphemeralOwner()); 79 | 80 | /* 81 | Let ELECTION be a path of choice of the application. To volunteer to be a leader: 82 | 1.Create znode z with path "ELECTION/n_" with both SEQUENCE and EPHEMERAL flags; 83 | 2.Let C be the children of "ELECTION", and i be the sequence number of z; 84 | 3.Watch for changes on "ELECTION/n_j", where j is the smallest sequence number such that j < i and n_j is a znode in C; 85 | 86 | Upon receiving a notification of znode deletion: 87 | 1.Let C be the new set of children of ELECTION; 88 | 2.If z is the smallest node in C, then execute leader procedure; 89 | 3.Otherwise, watch for changes on "ELECTION/n_j", where j is the smallest sequence number such that j < i and n_j is a znode in C; 90 | */ 91 | } 92 | 93 | public void newLeaderElection() throws KeeperException, InterruptedException{ 94 | 95 | List children = zk.getChildren(PATH, false); 96 | 97 | String tmp = children.get(0); 98 | 99 | for(String s : children){ 100 | if(tmp.compareTo(s) > 0) 101 | tmp = s; 102 | } 103 | 104 | // i contains the smallest sequence number 105 | String leader = PATH + "/" + tmp; 106 | Stat s = zk.exists(leader, true); 107 | 108 | // syso 109 | System.out.println("CLIENT ONE :: Leader is the owner of znode: " + leader); 110 | System.out.println("CLIENT ONE :: Leader id: " + s.getEphemeralOwner()); 111 | } 112 | 113 | 114 | @Override 115 | public void process(WatchedEvent event) { 116 | 117 | switch (event.getType()){ 118 | 119 | case NodeChildrenChanged: 120 | System.out.println("CLIENT ONE :: NodeChildrenChanged | ZNode: " + event.getPath()); 121 | break; 122 | 123 | case NodeCreated: 124 | System.out.println("CLIENT ONE :: NodeCreated | ZNode: " + event.getPath()); 125 | break; 126 | 127 | case NodeDataChanged: 128 | System.out.println("CLIENT ONE :: NodeDataChanged | ZNode: " + event.getPath()); 129 | break; 130 | 131 | case NodeDeleted: 132 | System.out.println("CLIENT ONE :: NodeDeleted | ZNode: " + event.getPath()); 133 | System.out.println("CLIENT ONE :: Leader was lost, newLeaderElection started."); 134 | try { 135 | newLeaderElection(); 136 | } catch (KeeperException e) { 137 | e.printStackTrace(); 138 | } catch (InterruptedException e) { 139 | e.printStackTrace(); 140 | } 141 | break; 142 | 143 | case None: 144 | 145 | switch (event.getState()){ 146 | 147 | case Disconnected: 148 | System.out.println("CLIENT ONE :: Disconnected."); 149 | break; 150 | 151 | case Expired: 152 | System.out.println("CLIENT ONE :: Expired."); 153 | break; 154 | 155 | case NoSyncConnected: 156 | System.out.println("CLIENT ONE :: NoSyncConnected - Deprecated"); 157 | break; 158 | 159 | case SyncConnected: 160 | System.out.println("CLIENT ONE :: SyncConnected."); 161 | break; 162 | 163 | case Unknown: 164 | System.out.println("CLIENT ONE :: Unknown - Deprecated"); 165 | break; 166 | } 167 | 168 | } 169 | 170 | } 171 | 172 | 173 | public static void main (String[] args){ 174 | 175 | try { 176 | new ZooKeeperClientOne(); 177 | } catch (KeeperException e) { 178 | e.printStackTrace(); 179 | } catch (InterruptedException e) { 180 | e.printStackTrace(); 181 | } catch (IOException e) { 182 | e.printStackTrace(); 183 | } 184 | 185 | } 186 | 187 | } 188 | --------------------------------------------------------------------------------