package com.thenetcircle.comsumerdispatcher.distribution.watcher;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import com.thenetcircle.comsumerdispatcher.distribution.DistributionManager;
import com.thenetcircle.comsumerdispatcher.distribution.DistributionTreeConstants;
import com.thenetcircle.comsumerdispatcher.thread.ConsumerJobExecutorPool;
import com.thenetcircle.comsumerdispatcher.util.QueueUtil;
public class QueuePurgeWatcher extends BaseJobPoolLevelWatcher implements IQueuePurgeWatcher {
private static Log _logger = LogFactory.getLog(QueuePurgeWatcher.class);
@Override
public void register(ConsumerJobExecutorPool pool) {
super.register(pool);
if (DistributionManager.getInstance().isStandalone())
return;
_logger.info("[Distribution Watcher] going to register queue purge watcher...");
mutex = new Integer(-1);
try {
//watchOrGetNode(true);
} catch (Exception e) {
_logger.error("[Distribution Purge Watcher] error while trying to watch." + e, e);
}
}
@Override
protected void preExecute() {
if (DistributionManager.getInstance().isStandalone()) {
pool.stopAllExecutors();
} else {
// use events to stop all threads
try {
// set count node to 0 so that all applications will stop all workers
try {
_logger.info("[Distribution Purge Watcher] set the count node to 0 so that to stop all running workers... ");
String countNode = String.format(DistributionTreeConstants.CD_ROOT_DOMAIN_QUEUEONSERVER_COUNT, getDomainName(), pool.getJobDefinition().getLogicName());
zk.setData(countNode, "0".getBytes(), -1);
} catch (Exception e) {
_logger.error("[Distribution Purge Watcher] error to set value of 0 to count node: " + e, e);
}
while (true) {
synchronized (mutex) {
// watch on not-running node
List<String> list = zk.getChildren(findTheNodePathToWatch(), new Watcher() {
@Override
public synchronized void process(WatchedEvent event) {
_logger.info("[Distribution Purge Watcher] received one event...");
synchronized (mutex) {
mutex.notify();
}
}
});
if (list.size() < DistributionManager.getInstance().getLivingJoinedMemberNum()) {
mutex.wait(); //TODO FIXME while start the application up, if the count is alread set to 0, need to add 'CD_ROOT_DOMAIN_QUEUEONSERVER_NOTRUNNING_SUBNODES' expicitly
} else {
break; // enough nodes, out of loop. meaning all running worker stopped, can continue to purge
}
}
}
} catch (Exception e) {
_logger.error("[Distribution Purge Watcher] prePurge failed for job: " + pool.getJobDefinition().getLogicName() + " on domain: " + pool.getJobDefinition().getUrl() + e, e);
throw new RuntimeException("[Distribution Purge Watcher] prePurge failed", e);
}
}
}
@Override
protected void doExecute() {
QueueUtil.purgeQueue(pool.getJobDefinition());
}
@Override
protected void postExecute() {
if (DistributionManager.getInstance().isStandalone()) {
pool.startJobExecutors();
} else {
String num = String.valueOf(pool.getJobDefinition().getCount());
_logger.info("[Distribution Purge Watcher] set the count node to " + num + " so that all workers start running ... ");
String countNode = String.format(DistributionTreeConstants.CD_ROOT_DOMAIN_QUEUEONSERVER_COUNT, getDomainName(), pool.getJobDefinition().getLogicName());
try {
zk.setData(countNode, num.getBytes(), -1);
} catch (Exception e) {
_logger.error("[Distribution Purge Watcher] error when trying to set new count value after purging queue: " + e, e);
}
}
}
@Override
public void process(WatchedEvent event) {
}
@Override
protected String findTheNodePathToWatch() {
return String.format(DistributionTreeConstants.CD_ROOT_DOMAIN_QUEUEONSERVER_NOTRUNNING, getDomainName(), pool.getJobDefinition().getLogicName());
}
@Override
protected Watcher getWatcher() {
return this;
}
}