package com.thenetcircle.comsumerdispatcher.distribution.watcher; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs.Ids; import com.thenetcircle.comsumerdispatcher.distribution.DistributionManager; import com.thenetcircle.comsumerdispatcher.distribution.DistributionTreeConstants; import com.thenetcircle.comsumerdispatcher.thread.ConsumerJobExecutorPool; public class CountChangedWatcher extends BaseJobPoolLevelWatcher implements ICountChangedWatcher { private static Log _logger = LogFactory.getLog(CountChangedWatcher.class); protected int numToSet = 0; protected String newSubNode = null; @Override public void register(ConsumerJobExecutorPool pool) { super.register(pool); if (DistributionManager.getInstance().isStandalone()) return; _logger.info("[Distribution Watcher] going to register count watcher..."); mutex = new Integer(-1); try { watchOrGetNode(true); } catch (Exception e) { _logger.error("[Distribution CountChanged Watcher] error while trying to watch." + e, e); } } @Override public void process(WatchedEvent event) { if(event.getType() == Watcher.Event.EventType.NodeDataChanged) { _logger.info("[Distribution CountChanged Watcher] got countchanged event...."); String numStr; try { numStr = watchOrGetNode(false); pool.setJobExecutorNum(Integer.valueOf(numStr)); if (pool.getActiveJobExecutorCount() <= 0) { // if all threads stopped in the pool, give signal of purging by adding one child under purge node; String purgeSubNode = String.format(DistributionTreeConstants.CD_ROOT_DOMAIN_QUEUEONSERVER_NOTRUNNING_SUBNODES, getDomainName(), pool.getJobDefinition().getLogicName()); newSubNode = zk.create(purgeSubNode, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); _logger.info("[Distribution CountChanged Watcher] since no worker in pool for queue" + getQueueJobNodeName() + " added subnode to purge node: " + newSubNode); } else { if(newSubNode != null && zk.exists(newSubNode, false) != null) { _logger.info("[Distribution CountChanged Watcher] goint to delete corresponding not running child node: " + newSubNode); zk.delete(newSubNode, -1); } } } catch (Exception e) { _logger.error("[Distribution CountChanged Watcher] error while processing watched event" + e, e); } } try { watchOrGetNode(true); } catch (Exception e) { _logger.error(e, e); } } @Override protected String findTheNodePathToWatch() { return String.format(DistributionTreeConstants.CD_ROOT_DOMAIN_QUEUEONSERVER_COUNT, getDomainName(), pool.getJobDefinition().getLogicName()); } @Override protected Watcher getWatcher() { return this; } @Override protected void doExecute() { if (DistributionManager.getInstance().isStandalone()) { pool.setJobExecutorNum(Integer.valueOf(numToSet)); } else { try { zk.setData(findTheNodePathToWatch(), String.valueOf(numToSet).getBytes(), -1); } catch (Exception e) { _logger.error("[Distribution CountChanged Watcher] error to set data for node: " + e, e); } } } @Override protected void preExecute() { } @Override protected void postExecute() { } /** * the number of jobs to be removed (- value) or added (+ value) * @param numToExecute */ public void setNumToSet(int deltaToExecute) { this.numToSet = deltaToExecute; } }