package com.thenetcircle.comsumerdispatcher.distribution; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.server.ServerConfig; import org.apache.zookeeper.server.ZooKeeperServerMain; import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException; import com.thenetcircle.comsumerdispatcher.util.HttpUtil; public class DistributionManager { private static Log _logger = LogFactory.getLog(DistributionManager.class); private static DistributionManager _self = null; protected Thread distributionThread; protected ServerConfig sc; protected ZooKeeper zk; /** * the type of how the application is running as. * -1: stand alone * 1: distribution client * 2: distribution server */ protected int runType = RUNTYPE_STANDALONE; public static int RUNTYPE_STANDALONE = -1; public static int RUNTYPE_DIST_CLIENT = 1; public static int RUNTYPE_DIST_SERVER = 2; public synchronized static DistributionManager getInstance() { if (null == _self) { _self = new DistributionManager(); } return _self; } public boolean isDistributionMaster() { return (runType == RUNTYPE_DIST_SERVER); } public boolean isDistributionClient() { return (runType == RUNTYPE_DIST_CLIENT); } public boolean isStandalone() { return (runType == RUNTYPE_STANDALONE); } public ZooKeeper getZk() { return zk; } public void populateDataTree() { if (isDistributionMaster()) { try { DistributionDataPopulator pop = new DistributionDataPopulator(); pop.populateQueueServers(zk); pop.populateJobsForDomains(zk); pop.populateMembers(zk); pop.populateMonitorData(zk); _logger.info("[Distribution Population] finished successfully."); } catch (Exception e) { cleanIfStartsError(); _logger.error("[Distribution] populating data failed: " + e, e); } } } private DistributionManager() { String serverConfigPath = System.getProperty("distserver.cfg", null); String clientConfigPath = System.getProperty("distclient.address", null); if (serverConfigPath == null && clientConfigPath == null) { _logger.info("[Distribution] starts up as standalone, will laod data from job.xml...."); runType = RUNTYPE_STANDALONE; return; } // the followings are for distributed version if (clientConfigPath != null) { _logger.info("[Distribution] starts up as client, will laod data from distribution server...."); runType = RUNTYPE_DIST_CLIENT; initZkConnection(clientConfigPath); while(getLivingJoinedMemberNum() < 1) { _logger.info("[Distribution] seems master is not up. wait for master to finishe starting up...."); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } else if (serverConfigPath != null) { _logger.info("[Distribution] starts up as master, needs to start distribution server and populate data to server ...."); runType = RUNTYPE_DIST_SERVER; // this is master, need to start distribution server and populate data to server loadDistributionServerConfig(serverConfigPath); startupServer(); initZkConnection(sc.getClientPortAddress().getHostName() + ":" + sc.getClientPortAddress().getPort()); // populate data to server populateDataTree(); } updateJoinedMemberNode(); } protected void updateJoinedMemberNode() { String hostname = HttpUtil.getLocalHostName(); try { zk.create(DistributionTreeConstants.JOINED_MEMBERS + "/" + hostname, hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); } catch (Exception e) { _logger.error(e, e); } } public int getLivingJoinedMemberNum() { int size = 0; try { size = zk.getChildren(DistributionTreeConstants.JOINED_MEMBERS, false).size(); } catch (Exception e) { _logger.error(e, e); } return size; } protected void initZkConnection(String hostPort) { // init the zk connnection try { zk = new ZooKeeper(hostPort, 500000, null); } catch (IOException e) { _logger.error("[Distribution Manager] error on inilization: " + e, e); } } protected void loadDistributionServerConfig(final String configPath) { sc = new ServerConfig(); try { sc.parse(configPath); } catch (ConfigException e) { _logger.error("[Distribution] error while loading distribution config: " + configPath + e, e); } } public void cleanTheOldServerData() { try { FileUtils.deleteDirectory(new File(sc.getDataDir())); } catch (IOException e) { _logger.error(e, e); } } protected void startupServer() { if (isDistributionMaster()) { cleanTheOldServerData(); distributionThread = new Thread() { @Override public void run() { try { ZooKeeperServerMain zs = new ZooKeeperServerMain(); zs.runFromConfig(sc); _logger.info("[Distribution] distribution server started up.... host:" + sc.getClientPortAddress().getHostName() + ";address:" + sc.getClientPortAddress().getAddress().getHostAddress() + ";port:" + sc.getClientPortAddress().getPort()); } catch (Exception e) { _logger.error(e, e); cleanIfStartsError(); } _logger.info("[Distribution] distribution server shutdown...."); } }; distributionThread.setDaemon(true); distributionThread.start(); try { Thread.sleep(1000); } catch (Exception e) { _logger.error(e, e); } } } protected void cleanIfStartsError() { distributionThread = null; } }