package com.alipay.bluewhale.core.task.acker; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import backtype.storm.Config; import backtype.storm.task.IBolt; 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.utils.StormUtils; /** * akcer ԭ�� * 1.spout����һ��tuple�󣬳��˻������bolt�����⣬���ᷢ����acker,��Ϣ����Ϊinit,ͬʱ���ػ�����TimeCacheMap����洢��tuple * 2.bolt�ڴ��������tuple����tuple��,��ͨ��ack��fail��acker������Ϣ * 3.acker���յ��󣬻��ж�����tuple���Ƿ�ȫ������ɹ�������������ʧ�ܣ�Ȼ������Ϣ��tuple��Ӧ��Դspout * 4.spout���TimeCacheMap�Ļ��壬spout��ack��fail�����ᱻ���ã������ﲢû���Զ������ط�-��Ҫҵ����fail��ack���Լ���ɡ� * @author yannian * */ public class Acker implements IBolt{ public static String ACKER_COMPONENT_ID = "__acker"; public static String ACKER_INIT_STREAM_ID = "__ack_init"; public static String ACKER_ACK_STREAM_ID = "__ack_ack"; public static String ACKER_FAIL_STREAM_ID = "__ack_fail"; private static Logger LOG = Logger.getLogger(Acker.class); private OutputCollector collector = null; private TimeCacheMap pending = null; // update_ack ��current_set��:val��ֵ��value����xor���� private static synchronized void update_ack(AckObject current_set, Object value) { Long old = current_set.val; if (old == null) { old = 0l; } Long newvalue = StormUtils.bit_xor(old, value); current_set.val = newvalue; } // acker_emit_direct ��values��Ϣ���͵�Ŀ��task // public static void acker_emit_direct(OutputCollector collector, Integer task, String stream, List values) { // } // prepare ����TimeCacheMap������������msg_id @Override public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) { this.collector = collector; String key=Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS; pending = new TimeCacheMap(StormUtils.parseInt(stormConf.get(key))); } // execute ackerһ����������Ϣ��ACKER_INIT,ACKER-ACK,ACKER_FAIL,��������ʼ�����ɹ���ʧ�� // TimeCacheMap�е�value�洢����������Ϊ{":val":"xor message_id",":spout-task":"soput��task_id",":failed":"����ʧ��"} // ��val=0��failed=true��ʱ��ֱ�����Ӧ��spout����ack��fail��Ϣ��spout���ж�ȷ���Ƿ����·��ʹ�tuple @Override public void execute(Tuple input) { Object id = input.getValue(0); AckObject curr = (AckObject) pending.get(id); if (curr == null) { curr = new AckObject(); } String stream_id = input.getSourceStreamId(); if (stream_id.equals(Acker.ACKER_INIT_STREAM_ID)) { Acker.update_ack(curr, input.getValue(1)); curr.spout_task = input.getValue(2); } if (stream_id.equals(Acker.ACKER_ACK_STREAM_ID)) { Acker.update_ack(curr, input.getValue(1)); } if (stream_id.equals(Acker.ACKER_FAIL_STREAM_ID)) { curr.failed = true; } pending.put(id, curr); Integer task = (Integer) curr.spout_task; if (task != null) { Long val = (Long) curr.val; if (new Long(0).equals(val)) { pending.remove(id); List values =StormUtils.mk_list(id); collector.emitDirect(task, Acker.ACKER_ACK_STREAM_ID, values); } boolean isFail = (Boolean) curr.failed; if (isFail) { pending.remove(id); List values = StormUtils.mk_list(id); collector.emitDirect(task, Acker.ACKER_FAIL_STREAM_ID, values); } } collector.ack(input); } @Override public void cleanup() { } }