/** * Copyright 2008 the original author or authors. * * 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 net.sf.katta.zk; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.util.Arrays; import java.util.HashMap; import net.sf.katta.util.KattaException; import net.sf.katta.util.NetworkUtil; import net.sf.katta.util.ZkConfiguration; import org.apache.log4j.Logger; import org.apache.zookeeper.server.NIOServerCnxn; import org.apache.zookeeper.server.ZooKeeperServer; import org.apache.zookeeper.server.NIOServerCnxn.Factory; import org.apache.zookeeper.server.quorum.QuorumPeer; import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer; public class ZkServer { private final static Logger LOG = Logger.getLogger(ZkServer.class); public static final int DEFAULT_PORT = 2181; private QuorumPeer _quorumPeer; private ZooKeeperServer _zk; private Factory _nioFactory; public ZkServer(final ZkConfiguration conf) throws KattaException { final String[] localHostNames = NetworkUtil.getLocalHostNames(); String names = ""; for (int i = 0; i < localHostNames.length; i++) { final String name = localHostNames[i]; names += " " + name; if (i + 1 != localHostNames.length) { names += ","; } } LOG.info("Starting ZkServer on: [" + names + "] ..."); startZooKeeperServer(conf); } // check if this server has to start a zookeeper server private void startZooKeeperServer(final ZkConfiguration conf) throws KattaException { final String[] localhostHostNames = NetworkUtil.getLocalHostNames(); final String servers = conf.getZKServers(); // check if this server needs to start a _client server. int pos = -1; LOG.debug("check if hostNames " + servers + " is in list: " + Arrays.asList(localhostHostNames)); if ((pos = NetworkUtil.hostNamesInList(servers, localhostHostNames)) != -1) { // yes this server needs to start a zookeeper server final String[] hosts = servers.split(","); final String[] hostSplitted = hosts[pos].split(":"); int port = DEFAULT_PORT; if (hostSplitted.length > 1) { port = Integer.parseInt(hostSplitted[1]); } // check if this machine is already something running.. if (NetworkUtil.isPortFree(port)) { final int tickTime = conf.getZKTickTime(); final File dataDir = conf.getZKDataDir(); final File dataLogDir = conf.getZKDataLogDir(); dataDir.mkdirs(); dataLogDir.mkdirs(); if (hosts.length > 1) { // multiple zk servers LOG.info("Start distributed zookeeper server..."); startQuorumPeer(conf, localhostHostNames, hosts, tickTime, dataDir, dataLogDir); } else { // single zk server LOG.info("Start single zookeeper server..."); startSingleZkServer(tickTime, dataDir, dataLogDir, port); } LOG.info("data dir: " + dataDir.getAbsolutePath()); LOG.info("data log dir: " + dataLogDir.getAbsolutePath()); } else { // TODO jz: shoudn't we better throw an exception LOG.error("Zookeeper port " + port + " was already in use. Running in single machine mode?"); } } } private void startSingleZkServer(final int tickTime, final File dataDir, final File dataLogDir, final int port) { try { // ServerStats.registerAsConcrete(); _zk = new ZooKeeperServer(dataDir, dataLogDir, tickTime); _nioFactory = new NIOServerCnxn.Factory(port); // _nioFactory = new ZkNioFactory(port); _nioFactory.startup(_zk); } catch (final IOException e) { throw new RuntimeException("Unable to start single ZooKeeper server.", e); } catch (final InterruptedException e) { LOG.warn("ZooKeeper server was interrupted.", e); } } private void startQuorumPeer(final ZkConfiguration conf, final String[] localhostHostNames, final String[] hosts, final int tickTime, final File dataDir, final File dataLogDir) { LOG.info("Starting ZooKeeper ZkServer..."); // final ArrayList<QuorumServer> peers = new ArrayList<QuorumServer>(); HashMap<Long, QuorumServer> peers = new HashMap<Long, QuorumServer>(); long myId = -1; for (int i = 0; i < hosts.length; i++) { final String[] hostAndPort = hosts[i].split(":"); final String host = hostAndPort[0]; final int port = Integer.parseInt(hostAndPort[1]); final InetSocketAddress inetSocketAddress = new InetSocketAddress(host, port); peers.put(new Long(i), new QuorumServer(i, inetSocketAddress)); if (NetworkUtil.hostNameInArray(localhostHostNames, host)) { myId = i; } } final int initLimit = conf.getZKInitLimit(); final int syncLimit = conf.getZKSyncLimit(); final int electionAlg = 0; final int clientPort = conf.getZKClientPort(); try { _quorumPeer = new QuorumPeer(peers, dataDir, dataLogDir, clientPort, electionAlg, myId, tickTime, initLimit, syncLimit); // _quorumPeer = new QuorumPeer(peers, dataDir, dataLogDir, clientPort, electionAlg,myId, myPort, myId, tickTime, // initLimit, syncLimit); _quorumPeer.start(); } catch (final IOException e) { throw new RuntimeException("Could not start QuorumPeer ZooKeeper server.", e); } } public void join() { if (_quorumPeer != null) { try { _quorumPeer.join(); } catch (final InterruptedException e) { LOG.info("QuorumPeer was interruped.", e); } finally { _quorumPeer.shutdown(); } } else if (_nioFactory != null) { try { _nioFactory.join(); } catch (final InterruptedException e) { LOG.info("Nio server was interruped.", e); } finally { _nioFactory.shutdown(); } _zk.shutdown(); // ServerStats.unregister(); } } public static void main(final String[] args) throws KattaException { if (args.length != 1) { usage(); System.exit(1); } final ZkConfiguration conf = new ZkConfiguration(); final ZkServer zkServer = new ZkServer(conf); zkServer.join(); } private static void usage() { System.out.println("net.sf.katta.ZkServer"); } public void shutdown() { LOG.info("Shutting down server..."); if (_nioFactory != null) { _nioFactory.shutdown(); } if (_quorumPeer != null) { _quorumPeer.shutdown(); } // ServerStats.unregister(); } }