package org.act.tstream.daemon.worker;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.act.tstream.callback.AsyncLoopThread;
import org.apache.log4j.Logger;
import backtype.storm.messaging.IConnection;
import backtype.storm.messaging.IContext;
import backtype.storm.scheduler.WorkerSlot;
import org.act.tstream.cluster.ClusterState;
import org.act.tstream.cluster.StormClusterState;
import org.act.tstream.daemon.worker.metrics.MetricReporter;
import org.act.tstream.task.ShutdownableDameon;
import org.act.tstream.task.TaskShutdownDameon;
import org.act.tstream.utils.JStormUtils;
/**
* Shutdown worker
*
* @author yannian/Longda
*
*/
public class WorkerShutdown implements ShutdownableDameon {
private static Logger LOG = Logger.getLogger(WorkerShutdown.class);
public static final String HOOK_SIGNAL = "USR2";
private List<TaskShutdownDameon> shutdowntasks;
private AtomicBoolean active;
private ConcurrentHashMap<WorkerSlot, IConnection> nodeportSocket;
private IContext context;
private List<AsyncLoopThread> threads;
private StormClusterState zkCluster;
private ClusterState cluster_state;
private MetricReporter metricReporter;
// active nodeportSocket context zkCluster zkClusterstate
public WorkerShutdown(WorkerData workerData,
List<TaskShutdownDameon> _shutdowntasks,
List<AsyncLoopThread> _threads, MetricReporter metricReporter) {
this.shutdowntasks = _shutdowntasks;
this.threads = _threads;
this.active = workerData.getActive();
this.nodeportSocket = workerData.getNodeportSocket();
this.context = workerData.getContext();
this.zkCluster = workerData.getZkCluster();
this.cluster_state = workerData.getZkClusterstate();
this.metricReporter = metricReporter;
Runtime.getRuntime().addShutdownHook(new Thread(this));
// PreCleanupTasks preCleanupTasks = new PreCleanupTasks();
// // install signals
// Signal sig = new Signal(HOOK_SIGNAL);
// Signal.handle(sig, preCleanupTasks);
}
@Override
public void shutdown() {
active.set(false);
metricReporter.shutdown();
// shutdown tasks
for (ShutdownableDameon task : shutdowntasks) {
task.shutdown();
}
// shutdown worker's demon thread
// refreshconn, refreshzk, hb, drainer
for (AsyncLoopThread t : threads) {
LOG.info("Begin to shutdown " + t.getThread().getName());
t.cleanup();
JStormUtils.sleepMs(100);
t.interrupt();
// try {
// t.join();
// } catch (InterruptedException e) {
// LOG.error("join thread", e);
// }
LOG.info("Successfully " + t.getThread().getName());
}
// send data to close connection
for (WorkerSlot k : nodeportSocket.keySet()) {
IConnection value = nodeportSocket.get(k);
value.close();
}
context.term();
// close ZK client
try {
zkCluster.disconnect();
cluster_state.close();
} catch (Exception e) {
// TODO Auto-generated catch block
LOG.info("Shutdown error,", e);
}
JStormUtils.halt_process(0, "!!!Shutdown!!!");
}
public void join() throws InterruptedException {
for (TaskShutdownDameon task : shutdowntasks) {
task.join();
}
for (AsyncLoopThread t : threads) {
t.join();
}
}
public boolean waiting() {
Boolean isExistsWait = false;
for (ShutdownableDameon task : shutdowntasks) {
if (task.waiting()) {
isExistsWait = true;
break;
}
}
for (AsyncLoopThread thr : threads) {
if (thr.isSleeping()) {
isExistsWait = true;
break;
}
}
return isExistsWait;
}
@Override
public void run() {
// TODO Auto-generated method stub
shutdown();
}
// class PreCleanupTasks implements SignalHandler {
//
// @Override
// public void handle(Signal arg0) {
// LOG.info("Receive " + arg0.getName() + ", begin to do pre_cleanup job");
//
// for (ShutdownableDameon task : shutdowntasks) {
// task.shutdown();
// }
//
// LOG.info("Successfully do pre_cleanup job");
// }
//
// }
}