com.bennavetta.aeneas.zookeeper.manager.ZooKeeperManager.java Source code

Java tutorial

Introduction

Here is the source code for com.bennavetta.aeneas.zookeeper.manager.ZooKeeperManager.java

Source

/**
 * Copyright 2015 Benjamin Navetta
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bennavetta.aeneas.zookeeper.manager;

import com.bennavetta.aeneas.zookeeper.*;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Manages ZooKeeper configuration.
 */
public class ZooKeeperManager implements Watcher, ServerRegistryWatcher.Listener {
    private static final Logger LOG = LoggerFactory.getLogger(ZooKeeperManager.class);
    private final int CONNECTION_TIMEOUT = 5000;

    private final ServerRegistry registry;
    private final ZooKeeper zk;

    private ServerRegistryWatcher watcher;

    public ZooKeeperManager(ServerRegistry registry) throws ZkException, IOException {
        this.registry = registry;
        this.zk = initialCluster();
    }

    private ZooKeeper initialCluster() throws ZkException, IOException {
        ImmutableList<ZkServer> servers = registry.getServers();
        if (servers.isEmpty()) {
            // TODO: wait for cluster members - https://github.com/coreos/etcd/issues/1516 would help
            throw new IllegalStateException("No cluster members");
        } else {
            return new ZooKeeper(Servers.toConnectionString(servers), CONNECTION_TIMEOUT, this);
        }
    }

    public void startMonitoring() throws ZkException {
        watcher = registry.watch(this);
        watcher.watch();
    }

    public void stopMonitoring() {
        watcher.stopWatching();
    }

    public void synchronizeMembers() throws ZkException {
        LOG.debug("Synchronizing ZooKeeper membership with registry");
        List<String> members = registry.getServers().stream().map(ZkServer::toServerSpec)
                .collect(Collectors.toList());

        try {
            zk.reconfig(null, null, members, -1, null);
        } catch (KeeperException | InterruptedException e) {
            throw new ZkException("Unable to reconfigure quorum", e);
        }
    }

    @Override
    public void process(WatchedEvent event) {
        LOG.debug("Received ZooKeeper event: {}", event);
    }

    @Override
    public void serverAdded(ZkServer server) {
        LOG.info("Adding server {}", server);

        try {
            byte[] newConfig = zk.reconfig(Lists.newArrayList(server.toServerSpec()), null, null, -1, null);
            LOG.debug("New ZooKeeper configuration: '{}'", new String(newConfig, Charsets.US_ASCII));
        } catch (KeeperException | InterruptedException e) {
            LOG.error("Error reconfiguring ZooKeeper", e);
        }
    }

    @Override
    public void serverRemoved(int serverId) {
        LOG.info("Removing server {}", serverId);

        try {
            byte[] newConfig = zk.reconfig(null, Lists.newArrayList(String.valueOf(serverId)), null, -1, null);
            LOG.debug("New ZooKeeper configuration: '{}'", new String(newConfig, Charsets.US_ASCII));
        } catch (InterruptedException | KeeperException e) {
            LOG.error("Error reconfiguring ZooKeeper", e);
        }
    }
}