package org.act.tstream.task.heartbeat; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.atomic.AtomicBoolean; import org.act.tstream.callback.RunnableCallback; import org.apache.log4j.Logger; import backtype.storm.Config; import org.act.tstream.cluster.StormClusterState; import org.act.tstream.daemon.worker.WorkerData; import org.act.tstream.stats.CommonStatsRolling; import org.act.tstream.task.TaskStatus; import org.act.tstream.task.UptimeComputer; import org.act.tstream.utils.JStormUtils; import org.act.tstream.utils.TimeUtils; /** * Task hearbeat * * @author yannian * */ public class TaskHeartbeatRunable extends RunnableCallback { private static final Logger LOG = Logger .getLogger(TaskHeartbeatRunable.class); private StormClusterState zkCluster; private String topology_id; private UptimeComputer uptime; private Map storm_conf; private Integer frequence; private AtomicBoolean active; private static Map<Integer, TaskStats> taskStatsMap = new HashMap<Integer, TaskStats>(); private static LinkedBlockingDeque<Event> eventQueue = new LinkedBlockingDeque<TaskHeartbeatRunable.Event>(); public static void registerTaskStats(int taskId, TaskStats taskStats) { Event event = new Event(Event.REGISTER_TYPE, taskId, taskStats); eventQueue.offer(event); } public static void unregisterTaskStats(int taskId) { Event event = new Event(Event.UNREGISTER_TYPE, taskId, null); eventQueue.offer(event); } public TaskHeartbeatRunable(WorkerData workerData) { this.zkCluster = workerData.getZkCluster(); this.topology_id = workerData.getTopologyId(); this.uptime = new UptimeComputer();; this.storm_conf = workerData.getStormConf(); this.active = workerData.getActive(); String key = Config.TASK_HEARTBEAT_FREQUENCY_SECS; Object time = storm_conf.get(key); frequence = JStormUtils.parseInt(time, 10); } @Override public void run() { Event event = eventQueue.poll(); while(event != null) { if (event.getType() == Event.REGISTER_TYPE) { taskStatsMap.put(event.getTaskId(), event.getTaskStats()); }else { taskStatsMap.remove(event.getTaskId()); } event = eventQueue.poll(); } Integer currtime = TimeUtils.current_time_secs(); for (Entry<Integer, TaskStats> entry : taskStatsMap.entrySet()) { Integer taskId = entry.getKey(); CommonStatsRolling taskStats = entry.getValue().getTaskStat(); String idStr = " " + topology_id + ":" + taskId + " "; try { TaskHeartbeat hb = new TaskHeartbeat(currtime, uptime.uptime(), taskStats.render_stats(), entry.getValue().getComponentType()); zkCluster.task_heartbeat(topology_id, taskId, hb); } catch (Exception e) { // TODO Auto-generated catch block String errMsg = "Failed to update heartbeat to ZK " + idStr + "\n"; LOG.error(errMsg, e); continue; } } LOG.info("update all task hearbeat ts " + currtime + "," + taskStatsMap.keySet()); } @Override public Object getResult() { if (active.get() == true) { return frequence; } else { LOG.info("Successfully shutdown Task's headbeat thread"); return -1; } } private static class Event { public static final int REGISTER_TYPE = 0; public static final int UNREGISTER_TYPE = 1; private final int type; private final int taskId; private final TaskStats taskStats; public Event(int type, int taskId, TaskStats taskStats) { this.type = type; this.taskId = taskId; this.taskStats = taskStats; } public int getType() { return type; } public int getTaskId() { return taskId; } public TaskStats getTaskStats() { return taskStats; } } }