package net.scharrenbach.zookeeper.test;
/*
* #%L
* ZooKeeper Run
* %%
* Copyright (C) 2013 Thomas Scharrenbach
* %%
* 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.
* #L%
*/
import java.io.File;
import java.io.IOException;
import org.apache.zookeeper.server.NIOServerCnxn;
import org.apache.zookeeper.server.NIOServerCnxn.Factory;
import org.apache.zookeeper.server.ServerConfig;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>
* This {@link Runnable} encapsulates a {@link ZooKeeperServer} and a
* conncection {@link Factory}.
* </p>
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*
*/
public class ZooKeeperServerRunnable extends Thread {
private static final Logger _log = LoggerFactory
.getLogger(ZooKeeperServerRunnable.class);
//
//
//
/**
* <p>
* Create a new instance of this runnable. The {@link ServerConfig} is read
* from a ZooKeeper configuration file.
* </p>
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*
* @param zkConfigFile
* @param addShutdownHook
* flag whether to add a shutdown hook for shutting down both the
* server and the connection factory.
* @return fresh {@link ZooKeeperServerRunnable} instance.
* @throws ConfigException
*/
public static final ZooKeeperServerRunnable newInstance(
String zkConfigFile, boolean addShutdownHook)
throws ConfigException {
final ServerConfig zkServerConfig = new ServerConfig();
zkServerConfig.parse(zkConfigFile);
return newInstance(zkServerConfig, addShutdownHook);
}
/**
* Create a new instance of this runnable.
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*
* @param zkServerConfig
* the {@link ZooKeeperServer} {@link ServerConfig}.
* @param addShutdownHook
* flag whether to add a shutdown hook for shutting down both the
* server and the connection factory.
*
* @return fresh {@link ZooKeeperServerRunnable} instance.
*/
public static final ZooKeeperServerRunnable newInstance(
ServerConfig zkServerConfig, boolean addShutdownHook) {
final ZooKeeperServer zkServer = initZKServer(zkServerConfig);
final Factory zkCnxnFactory = initZKCxnFactory(zkServerConfig);
final ZooKeeperServerRunnable runnable = new ZooKeeperServerRunnable(
zkServer, zkCnxnFactory);
if (addShutdownHook) {
addShutdownHooks(runnable);
}
return runnable;
}
/**
* Initialize the Zookeeper server with the specified configuration.
*
* @param zkServer
* @param zkServerConfig
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*/
private static ZooKeeperServer initZKServer(ServerConfig zkServerConfig) {
final ZooKeeperServer zkServer = new ZooKeeperServer();
// Configure Zookeeper server
_log.debug("Started configuring Zookeeper server...");
try {
zkServer.setTickTime(zkServerConfig.getTickTime());
zkServer.setMaxSessionTimeout(zkServerConfig.getMaxSessionTimeout());
zkServer.setMinSessionTimeout(zkServerConfig.getMinSessionTimeout());
zkServer.setTxnLogFactory(new FileTxnSnapLog(new File(
zkServerConfig.getDataLogDir()), new File(zkServerConfig
.getDataDir())));
} catch (IOException e) {
_log.error("Finished configuring Zookeeper server.");
throw new RuntimeException(e);
}
_log.debug("Finished configuring Zookeeper server.");
return zkServer;
}
/**
* Initialize the ZooKeeper connection factory.
*
* @param zkServerConfig
* @return
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*/
private static Factory initZKCxnFactory(ServerConfig zkServerConfig) {
_log.debug("Started creating Zookeeper connection factory...");
Factory zkCnxnFactory = null;
try {
zkCnxnFactory = new NIOServerCnxn.Factory(
zkServerConfig.getClientPortAddress(),
zkServerConfig.getMaxClientCnxns());
} catch (IOException e) {
_log.error("Error creating Zookeeper connection factory!", e);
throw new RuntimeException(e);
}
_log.debug("Finished creating Zookeeper connection factory.");
return zkCnxnFactory;
}
/**
* <p>
* Adds a shutdown hook for shutting down both the server and the connection
* factory. Runs {@link #shutdown()}.
* </p>
*
* @param zkServer
* @param zkCnxnFactory
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*
*/
private static void addShutdownHooks(
final ZooKeeperServerRunnable zooKeeperServerRunnable) {
zooKeeperServerRunnable.shutdown();
}
//
//
//
private final ZooKeeperServer _zkServer;
private final Factory _zkCnxnFactory;
//
//
//
/**
*
* @param zkConfigFile
* @throws ConfigException
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*/
public ZooKeeperServerRunnable(ZooKeeperServer zkServer,
Factory zkCnxnFactory) {
_zkServer = zkServer;
_zkCnxnFactory = zkCnxnFactory;
}
/**
* Starts the ZooKeeper server.
*
* @author Thomas Scharrenbach
* @version 3.3.0
* @since 3.3.0
*/
@Override
public void run() {
_log.info("Started starting Zookeeper...");
try {
_zkCnxnFactory.startup(_zkServer);
Thread.sleep(10);
} catch (IOException e) {
_log.error("Error starting Zookeeper!");
e.printStackTrace();
throw new RuntimeException(e);
} catch (InterruptedException e) {
_log.error("Error starting Zookeeper!");
e.printStackTrace();
throw new RuntimeException(e);
}
_log.info("Finished starting Zookeeper.");
}
public void shutdown() {
// Add shutdown hook that shuts down both the server and the connection
// factory.
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
super.run();
_log.info("Started shutting down ZooKeeper server...");
try {
if (_zkServer != null && _zkServer.isRunning()) {
_zkServer.shutdown();
}
} catch (Exception e) {
_log.error("Error shutting down ZooKeeper server!");
}
_log.info("Finished shutting down ZooKeeper server.");
_log.info("Started shutting down ZooKeeper connection factory...");
try {
if (_zkCnxnFactory != null && _zkCnxnFactory.isAlive()) {
_zkCnxnFactory.shutdown();
}
} catch (Exception e) {
_log.error("Error shutting down ZooKeeper connection factory!");
}
_log.info("Finished shutting down ZooKeeper connection factory.");
}
});
}
}