package org.shanbo.feluca.distribute.launch; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import org.apache.zookeeper.KeeperException; import org.shanbo.feluca.common.Constants; import org.shanbo.feluca.common.FelucaException; import org.shanbo.feluca.util.ZKClient; import org.shanbo.feluca.util.ZKClient.ChildrenWatcher; import org.shanbo.feluca.util.concurrent.ConcurrentExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * not seen by algorithms * * TODO * @author lgn * */ @Deprecated public class StartingGun { Logger log = LoggerFactory.getLogger(StartingGun.class); public final static String START_SIGNAL = "start"; public final static String FINISH_SIGNAL = "finish"; private ChildrenWatcher workerWatcher; private int totalWorkers; private int totalReduceServers; private AtomicInteger waitingWorkers; private String path; private int loop; public StartingGun(String taskName, int totalReduceServers, int totalWorkers) { this.path = Constants.Algorithm.ZK_ALGO_CHROOT + "/" + taskName; this.totalWorkers = totalWorkers; this.totalReduceServers = totalReduceServers; waitingWorkers = new AtomicInteger(0); } private void prepare() throws KeeperException, InterruptedException{ ZKClient.get().createIfNotExist(path + Constants.Algorithm.ZK_LOOP_PATH); ZKClient.get().createIfNotExist(path + Constants.Algorithm.ZK_WAITING_PATH); ZKClient.get().createIfNotExist(path + Constants.Algorithm.ZK_REDUCER_PATH); //DO NOT delete '/worker' and recreate it! It will cause a bug that the ZKclient will not be able to create children // Instead, delete it's children List<String> waitingList = ZKClient.get().getChildren(path + Constants.Algorithm.ZK_WAITING_PATH); for(String workerNode : waitingList){ ZKClient.get().forceDelete(path + Constants.Algorithm.ZK_WAITING_PATH + "/" + workerNode); } ZKClient.get().setData(path, START_SIGNAL.getBytes()); } private void startWatch() { workerWatcher = new ChildrenWatcher() { public void nodeRemoved(String node) { } public void nodeAdded(String node) { waitingWorkers.incrementAndGet(); if (waitingWorkers.get() == totalWorkers){ synchronized(StartingGun.class){ //Double check lock if (waitingWorkers.get() == totalWorkers){ setLoopSignal(); } } } } }; ZKClient.get().watchChildren(path + Constants.Algorithm.ZK_WAITING_PATH, workerWatcher); } private void setLoopSignal(){ waitingWorkers.set(0); String workerPath = path + Constants.Algorithm.ZK_WAITING_PATH; try { List<String> waitingList = ZKClient.get().getChildren(workerPath); for(String workerNode : waitingList){ ZKClient.get().forceDelete(workerPath + "/" + workerNode); } ZKClient.get().setData(path + Constants.Algorithm.ZK_LOOP_PATH, ("" + loop).getBytes()); } catch (Exception e) { log.error("all workers are ready. but error here :" + loop, e); } loop += 1; } public void start() throws KeeperException, InterruptedException{ this.prepare(); this.startWatch(); } public void close() throws InterruptedException, KeeperException{ ZKClient.get().destoryWatch(workerWatcher); ZKClient.get().forceDelete(path + Constants.Algorithm.ZK_LOOP_PATH); ZKClient.get().forceDelete(path + Constants.Algorithm.ZK_WAITING_PATH); System.out.println("startingGun of [" + path + "] closed" ); } public void waitForModelServersStarted() throws InterruptedException, ExecutionException, TimeoutException{ ConcurrentExecutor.submitAndWait(new Runnable() { public void run() { try{ while(ZKClient.get().getChildren(path + Constants.Algorithm.ZK_REDUCER_PATH).size()< totalReduceServers && ZKClient.get().getChildren(path + Constants.Algorithm.ZK_MODELSERVER_PATH).size() < totalWorkers){ try{ Thread.sleep(10); }catch (InterruptedException e) { break; } } } catch (InterruptedException e) { throw new FelucaException("waitForModelServerStarted InterruptedException ",e ); } catch (KeeperException e) { throw new FelucaException("waitForModelServerStarted KeeperException ",e ); } } }, 100000); } public void setFinish() throws KeeperException, InterruptedException{ ZKClient.get().setData(path, FINISH_SIGNAL.getBytes()); } public String toString() { return path + " of (" + totalWorkers+ ")" ; } }