use of org.apache.zookeeper.WatchedEvent in project pulsar by yahoo.
the class ZooKeeperSessionWatcherTest method testProcess1.
@Test
void testProcess1() {
WatchedEvent event = new WatchedEvent(EventType.None, KeeperState.Expired, null);
sessionWatcher.process(event);
assertTrue(sessionWatcher.isShutdownStarted());
assertEquals(shutdownService.getExitCode(), -1);
}
use of org.apache.zookeeper.WatchedEvent in project pulsar by yahoo.
the class ZooKeeperSessionWatcherTest method testProcess2.
@Test
void testProcess2() {
WatchedEvent event = new WatchedEvent(EventType.None, KeeperState.Disconnected, null);
sessionWatcher.process(event);
assertFalse(sessionWatcher.isShutdownStarted());
assertEquals(shutdownService.getExitCode(), 0);
}
use of org.apache.zookeeper.WatchedEvent in project pulsar by yahoo.
the class ZooKeeperSessionWatcherTest method testProcess3.
@Test
void testProcess3() {
WatchedEvent event = new WatchedEvent(EventType.NodeCreated, KeeperState.Expired, null);
sessionWatcher.process(event);
assertFalse(sessionWatcher.isShutdownStarted());
assertEquals(shutdownService.getExitCode(), 0);
}
use of org.apache.zookeeper.WatchedEvent in project pulsar by yahoo.
the class ZookeeperCacheTest method testGlobalZooKeeperCache.
@Test
void testGlobalZooKeeperCache() throws Exception {
OrderedSafeExecutor executor = new OrderedSafeExecutor(1, "test");
ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1);
MockZooKeeper zkc = MockZooKeeper.newInstance();
ZooKeeperClientFactory zkClientfactory = new ZooKeeperClientFactory() {
@Override
public CompletableFuture<ZooKeeper> create(String serverList, SessionType sessionType, int zkSessionTimeoutMillis) {
return CompletableFuture.completedFuture(zkc);
}
};
GlobalZooKeeperCache zkCacheService = new GlobalZooKeeperCache(zkClientfactory, -1, "", executor, scheduledExecutor);
zkCacheService.start();
zkClient = (MockZooKeeper) zkCacheService.getZooKeeper();
ZooKeeperDataCache<String> zkCache = new ZooKeeperDataCache<String>(zkCacheService) {
@Override
public String deserialize(String key, byte[] content) throws Exception {
return new String(content);
}
};
// Create callback counter
AtomicInteger notificationCount = new AtomicInteger(0);
ZooKeeperCacheListener<String> counter = (path, data, stat) -> {
notificationCount.incrementAndGet();
};
// Register counter twice and unregister once, so callback should be counted correctly
zkCache.registerListener(counter);
zkCache.registerListener(counter);
zkCache.unregisterListener(counter);
String value = "test";
zkClient.create("/my_test", value.getBytes(), null, null);
assertEquals(zkCache.get("/my_test").get(), value);
String newValue = "test2";
// case 1: update and create znode directly and verify that the cache is retrieving the correct data
assertEquals(notificationCount.get(), 0);
zkClient.setData("/my_test", newValue.getBytes(), -1);
zkClient.create("/my_test2", value.getBytes(), null, null);
// Wait for the watch to be triggered
while (notificationCount.get() < 1) {
Thread.sleep(1);
}
// retrieve the data from the cache and verify it is the updated/new data
assertEquals(zkCache.get("/my_test").get(), newValue);
assertEquals(zkCache.get("/my_test2").get(), value);
// The callback method should be called just only once
assertEquals(notificationCount.get(), 1);
// case 2: force the ZooKeeper session to be expired and verify that the data is still accessible
zkCacheService.process(new WatchedEvent(Event.EventType.None, KeeperState.Expired, null));
assertEquals(zkCache.get("/my_test").get(), newValue);
assertEquals(zkCache.get("/my_test2").get(), value);
// case 3: update the znode directly while the client session is marked as expired. Verify that the new updates
// is not seen in the cache
zkClient.create("/other", newValue.getBytes(), null, null);
zkClient.failNow(Code.SESSIONEXPIRED);
assertEquals(zkCache.get("/my_test").get(), newValue);
assertEquals(zkCache.get("/my_test2").get(), value);
try {
zkCache.get("/other");
fail("shuld have thrown exception");
} catch (Exception e) {
// Ok
}
// case 4: directly delete the znode while the session is not re-connected yet. Verify that the deletion is not
// seen by the cache
zkClient.failAfter(-1, Code.OK);
zkClient.delete("/my_test2", -1);
zkCacheService.process(new WatchedEvent(Event.EventType.None, KeeperState.SyncConnected, null));
assertEquals(zkCache.get("/other").get(), newValue);
// Make sure that the value is now directly from ZK and deleted
assertFalse(zkCache.get("/my_test2").isPresent());
// case 5: trigger a ZooKeeper disconnected event and make sure the cache content is not changed.
zkCacheService.process(new WatchedEvent(Event.EventType.None, KeeperState.Disconnected, null));
zkClient.create("/other2", newValue.getBytes(), null, null);
// case 6: trigger a ZooKeeper SyncConnected event and make sure that the cache content is invalidated s.t. we
// can see the updated content now
zkCacheService.process(new WatchedEvent(Event.EventType.None, KeeperState.SyncConnected, null));
// make sure that we get it
assertEquals(zkCache.get("/other2").get(), newValue);
zkCacheService.close();
executor.shutdown();
// Update shouldn't happen after the last check
assertEquals(notificationCount.get(), 1);
}
use of org.apache.zookeeper.WatchedEvent in project pulsar by yahoo.
the class LeaderElectionService method elect.
/**
* We try to get the data in the ELECTION_ROOT node. If the node is present (i.e. leader is present), we store it in
* the currentLeader and keep a watch on the election node. If we lose the leader, then watch gets triggered and we
* do the election again. If the node does not exist while getting the data, we get NoNodeException. This means,
* there is no leader and we create the node at ELECTION_ROOT and write the leader broker's service URL in the node.
* Once the leader is known, we call the listener method so that leader can take further actions.
*/
private void elect() {
try {
byte[] data = zkClient.getData(ELECTION_ROOT, new Watcher() {
@Override
public void process(WatchedEvent event) {
log.warn("Type of the event is [{}] and path is [{}]", event.getType(), event.getPath());
switch(event.getType()) {
case NodeDeleted:
log.warn("Election node {} is deleted, attempting re-election...", event.getPath());
if (event.getPath().equals(ELECTION_ROOT)) {
log.info("This should call elect again...");
executor.execute(new Runnable() {
@Override
public void run() {
// If the node is deleted, attempt the re-election
log.info("Broker [{}] is calling re-election from the thread", pulsar.getWebServiceAddress());
elect();
}
});
}
break;
default:
log.warn("Got something wrong on watch: {}", event);
break;
}
}
}, null);
LeaderBroker leaderBroker = jsonMapper.readValue(data, LeaderBroker.class);
currentLeader.set(leaderBroker);
isLeader.set(false);
leaderListener.brokerIsAFollowerNow();
// If broker comes here it is a follower. Do nothing, wait for the watch to trigger
log.info("Broker [{}] is the follower now. Waiting for the watch to trigger...", pulsar.getWebServiceAddress());
} catch (NoNodeException nne) {
// There's no leader yet... try to become the leader
try {
// Create the root node and add current broker's URL as its contents
LeaderBroker leaderBroker = new LeaderBroker(pulsar.getWebServiceAddress());
ZkUtils.createFullPathOptimistic(pulsar.getLocalZkCache().getZooKeeper(), ELECTION_ROOT, jsonMapper.writeValueAsBytes(leaderBroker), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
// Update the current leader and set the flag to true
currentLeader.set(new LeaderBroker(leaderBroker.getServiceUrl()));
isLeader.set(true);
// Notify the listener that this broker is now the leader so that it can collect usage and start load
// manager.
log.info("Broker [{}] is the leader now, notifying the listener...", pulsar.getWebServiceAddress());
leaderListener.brokerIsTheLeaderNow();
} catch (NodeExistsException nee) {
// Re-elect the new leader
log.warn("Got exception [{}] while creating election node because it already exists. Attempting re-election...", nee.getMessage());
executor.execute(new Runnable() {
@Override
public void run() {
elect();
}
});
} catch (Exception e) {
// Kill the broker because this broker's session with zookeeper might be stale. Killing the broker will
// make sure that we get the fresh zookeeper session.
log.error("Got exception [{}] while creating the election node", e.getMessage());
pulsar.getShutdownService().shutdown(-1);
}
} catch (Exception e) {
// Kill the broker
log.error("Could not get the content of [{}], got exception [{}]. Shutting down the broker...", ELECTION_ROOT, e);
pulsar.getShutdownService().shutdown(-1);
}
}
Aggregations