package com.alipay.bluewhale.core.task;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import backtype.storm.task.TopologyContext;
import com.alipay.bluewhale.core.callback.RunnableCallback;
import com.alipay.bluewhale.core.cluster.ClusterState;
import com.alipay.bluewhale.core.cluster.Common;
import com.alipay.bluewhale.core.cluster.StormClusterState;
import com.alipay.bluewhale.core.cluster.StormConfig;
import com.alipay.bluewhale.core.cluster.StormZkClusterState;
import com.alipay.bluewhale.core.messaging.IConnection;
import com.alipay.bluewhale.core.messaging.IContext;
import com.alipay.bluewhale.core.stats.BaseTaskStatsRolling;
import com.alipay.bluewhale.core.task.common.TaskShutdownDameon;
import com.alipay.bluewhale.core.task.common.TasksCommon;
import com.alipay.bluewhale.core.task.error.ITaskReportErr;
import com.alipay.bluewhale.core.task.error.TaskReportError;
import com.alipay.bluewhale.core.task.error.TaskReportErrorAndDie;
import com.alipay.bluewhale.core.task.group.MkGrouper;
import com.alipay.bluewhale.core.task.heartbeat.TaskHeartbeatRunable;
import com.alipay.bluewhale.core.task.transfer.TaskSendTargets;
import com.alipay.bluewhale.core.task.transfer.UnanchoredSend;
import com.alipay.bluewhale.core.utils.AsyncLoopThread;
import com.alipay.bluewhale.core.utils.EvenSampler;
import com.alipay.bluewhale.core.utils.StormUtils;
import com.alipay.bluewhale.core.utils.UptimeComputer;
import com.alipay.bluewhale.core.work.WorkerHaltRunable;
import com.alipay.bluewhale.core.work.transfer.WorkerTransfer;
/**
* task������
*
* @author yannian
*
*/
public class Task {
private final static Logger LOG = Logger.getLogger(Task.class);
@SuppressWarnings("rawtypes")
private Map stormConf;
private TopologyContext topologyContext;
private TopologyContext userContext;
private String topologyid;
private IContext mqContext;
private AtomicBoolean stormActive;
private WorkerTransfer workerTransfer;
private WorkerHaltRunable workHalt;
private Integer taskid;
private String componentid;
private AtomicBoolean active = new AtomicBoolean(true);
// ��������ʱ�������
private UptimeComputer uptime = new UptimeComputer();
private StormClusterState zkCluster;
private Object taskObj;
private BaseTaskStatsRolling taskStats;
@SuppressWarnings("rawtypes")
public Task(Map conf, Map stormConf, TopologyContext topologyContext,
TopologyContext userContext, String topologyid, IContext mqContext,
ClusterState clusterState, AtomicBoolean stormActive,
WorkerTransfer workerTransfer, WorkerHaltRunable workHalt)
throws Exception {
this.topologyContext = topologyContext;
this.userContext = userContext;
this.topologyid = topologyid;
this.mqContext = mqContext;
this.stormActive = stormActive;
this.workerTransfer = workerTransfer;
this.workHalt = workHalt;
this.taskid = topologyContext.getThisTaskId();
this.componentid = topologyContext.getThisComponentId();
this.stormConf = TasksCommon.component_conf(stormConf, topologyContext,
componentid);
LOG.info("Loading task " + componentid + ":" + taskid);
this.zkCluster = new StormZkClusterState(clusterState);
// ��ȡtask_obj����,��ʵ���Ǹ���Component_id��ȡ���ε�SpoutSpec��bolt��StateSpoutSpec
this.taskObj = TasksCommon.get_task_object(
topologyContext.getRawTopology(), componentid);
// ����taskͳ�ƵĶ���-�μ�stats��
int samplerate = StormConfig.sampling_rate(stormConf);
this.taskStats = TasksCommon.mk_task_stats(taskObj, samplerate);
}
private TaskSendTargets makeSendTargets() {
String taskName = TasksCommon.get_readable_name(topologyContext);
EvenSampler statSample = StormConfig.mk_stats_sampler(stormConf);
//// ��ȡ��ǰtask��ÿ��streamӦ��������ЩcommponID,�Լ���������η����
// <Stream_id,<component,Grouping>>
Map<String, Map<String, MkGrouper>> streamComponentGrouper = TasksCommon
.outbound_components(topologyContext);
Map<Integer, String> task2Component = topologyContext
.getTaskToComponent();
Map<String, List<Integer>> component2Tasks = StormUtils
.reverse_map(task2Component);
return new TaskSendTargets(stormConf, taskName, streamComponentGrouper,
topologyContext, statSample, component2Tasks, taskStats);
}
private RunnableCallback mkExecutor(IConnection puller,
TaskSendTargets sendTargets) {
// ���������ϱ��ص�����ʵ�����ǵ���storm_cluster.report-task-error
ITaskReportErr reportError = new TaskReportError(zkCluster, topologyid,
taskid);
// �����������˳�����-ʵ�����ǵ����ϲ���report_error��������halt_process
TaskReportErrorAndDie reportErrorDie = new TaskReportErrorAndDie(
reportError, workHalt);
return TasksCommon.mk_executors(taskObj, workerTransfer, stormConf,
puller, sendTargets, stormActive, topologyContext, userContext,
taskStats, reportErrorDie);
}
public TaskShutdownDameon execute() throws Exception {
IConnection puller = mqContext.bind(topologyid, taskid);
// ���������߳�
TaskHeartbeatRunable hb = new TaskHeartbeatRunable(zkCluster, topologyid,
taskid, uptime, taskStats, active, stormConf);
AsyncLoopThread heartbeat_thread = new AsyncLoopThread(hb, true,
Thread.MAX_PRIORITY, true);
// ����tuple���ͺ�������ϵͳstream����startup��Ϣ
List<Object> msg = new ArrayList<Object>();
msg.add("startup");
// ����task���ն���
TaskSendTargets sendTargets = makeSendTargets();
UnanchoredSend.send(topologyContext, sendTargets, workerTransfer,
Common.SYSTEM_STREAM_ID, msg);
// �����̣߳���zeroMq�ж�ȡtuple,����spout��bolt���д���Ȼ����worker
RunnableCallback componsementExecutor = mkExecutor(puller, sendTargets);
AsyncLoopThread executor_threads = new AsyncLoopThread(
componsementExecutor);
AsyncLoopThread[] all_threads = { executor_threads, heartbeat_thread };
LOG.info("Finished loading task " + componentid + ":" + taskid);
return getShutdown(all_threads, heartbeat_thread, puller);
}
public TaskShutdownDameon getShutdown(AsyncLoopThread[] all_threads,
AsyncLoopThread heartbeat_thread, IConnection puller) {
TaskShutdownDameon shutdown = new TaskShutdownDameon(active, topologyid,
taskid, mqContext, all_threads, zkCluster, puller, taskObj,
heartbeat_thread);
return shutdown;
}
@SuppressWarnings("rawtypes")
public static TaskShutdownDameon mk_task(Map conf, Map stormConf,
TopologyContext topologyContext, TopologyContext userContext,
String stormId, IContext mqContext, ClusterState clusterState,
AtomicBoolean stormActive, WorkerTransfer workerTransfer,
WorkerHaltRunable workHalt) throws Exception {
Task t = new Task(conf, stormConf, topologyContext, userContext,
stormId, mqContext, clusterState, stormActive, workerTransfer,
workHalt);
return t.execute();
}
}