├── 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 |
--------------------------------------------------------------------------------