package com.alipay.bluewhale.core.task.executer;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.log4j.Logger;
import backtype.storm.Config;
import backtype.storm.serialization.KryoTupleDeserializer;
import backtype.storm.task.IBolt;
import backtype.storm.task.IOutputCollector;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.tuple.Tuple;
import backtype.storm.utils.TimeCacheMap;
import com.alipay.bluewhale.core.callback.RunnableCallback;
import com.alipay.bluewhale.core.cluster.StormConfig;
import com.alipay.bluewhale.core.messaging.IConnection;
import com.alipay.bluewhale.core.stats.BaseTaskStatsRolling;
import com.alipay.bluewhale.core.task.error.ITaskReportErr;
import com.alipay.bluewhale.core.task.transfer.TaskSendTargets;
import com.alipay.bluewhale.core.utils.EvenSampler;
import com.alipay.bluewhale.core.utils.StormUtils;
import com.alipay.bluewhale.core.work.transfer.WorkerTransfer;
/**
*
* bolt ������
*
* chages
*
* �Ұ�mk-executors IBolt �е� tuple-start-times (ConcurrentHashMap.) pending-acks
* (ConcurrentHashMap.) ���������� TimeCacheMap����
*
* ��Щʱ��û��bolt�����һЩbug,�������ǵ��ã�ack����fail.���ʱ��spout��pending�ͻᳬʱ�����ͻ��ط����tuple.
* ������pending-acks��tuple-start-time��Ͳ��ᱻ������������ͻᵼ��ConcurrentHashMap
* ���Խ��Խ����������ĵ�ԭ�� Ŀǰ��ʹ��storm_conf.get(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS)
* �������,�����ó�ʱ��ʱ��
*
*
* @author yannian
*
*/
public class BoltExecutors extends RunnableCallback {
private static Logger LOG = Logger.getLogger(BoltExecutors.class);
private IConnection puller;
private AtomicBoolean zkActive;
private Integer task_id;
private IBolt bolt;
private KryoTupleDeserializer deserializer;
private TimeCacheMap<Tuple, Long> tuple_start_times;
private EvenSampler sampler;
private Exception errorReport = null;
public BoltExecutors(IBolt _bolt, WorkerTransfer _transfer_fn,
Map storm_conf, IConnection _puller, TaskSendTargets _send_fn,
AtomicBoolean _storm_active_atom,
TopologyContext _topology_context, TopologyContext _user_context,
BaseTaskStatsRolling _task_stats, ITaskReportErr _report_error) {
this.bolt = _bolt;
this.puller = _puller;
this.zkActive = _storm_active_atom;
this.task_id = _topology_context.getThisTaskId();
this.sampler = StormConfig.mk_stats_sampler(storm_conf);
String component_id = _topology_context.getThisComponentId();
String timeoutkey = Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS;
int message_timeout_secs = StormUtils.parseInt(storm_conf
.get(timeoutkey));
// ԭ���� tuple-start-times (ConcurrentHashMap.)
// ��Ҫ�Ƿ�ֹ ��bolt�У����ҵ������bug����ijһ���������ǵ���ack��fail���ͻᵼ������mapԽ��Խ��ֱ���ڴ治����
this.tuple_start_times = new TimeCacheMap<Tuple, Long>(
message_timeout_secs);
IOutputCollector output_collector = new BoltCollector(
message_timeout_secs, _report_error, _send_fn, _transfer_fn,
_topology_context, task_id, tuple_start_times, _task_stats);
LOG.info("Preparing bolt " + component_id + ":" + task_id);
bolt.prepare(storm_conf, _user_context, new OutputCollector(
output_collector));
LOG.info("Prepared bolt " + component_id + ":" + task_id);
deserializer = new KryoTupleDeserializer(storm_conf, _topology_context);
}
@Override
public void run() {
byte[] ser_msg = puller.recv();
if (ser_msg != null && ser_msg.length > 0) {
LOG.debug("Processing message");
Tuple tuple = deserializer.deserialize(ser_msg);
if (sampler.getResult()) {
tuple_start_times.put(tuple, System.currentTimeMillis());
}
try {
bolt.execute(tuple);
} catch (RuntimeException e) {
errorReport = e;
LOG.error("bolt execute error ", e);
} catch (Exception e) {
errorReport = e;
LOG.error("bolt execute error ", e);
}
}
}
@Override
public Object getResult() {
if (this.IsActive()) {
return 0;
} else {
return -1;
}
}
public boolean IsActive() {
return zkActive.get();
}
@Override
public Exception error() {
return errorReport;
}
}