package com.alibaba.jstorm.transactional; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import backtype.storm.generated.*; import backtype.storm.utils.Utils; import com.alibaba.jstorm.utils.JStormUtils; import backtype.storm.task.TopologyContext; public class TransactionCommon { public static final String BARRIER_STREAM_ID = "barrier_stream"; public static final String SUCCESS_STREAM_ID = "success_stream"; public static final String BARRIER_SNAPSHOT_FIELD = "barrier_snapshot"; public static final String BATCH_GROUP_ID_FIELD = "batch_group_id"; public static final long INIT_BATCH_ID = 0; public static final String ENABLE_TRANSACTION_CHECK_POINT = "enable.transaction.check.point"; public static final String TRANSACTION_STATEFUL_BOLT = "transaction.stateful.bolt"; public static final Object COMMIT_FAIL = new Object(); public static Set<String> getDownstreamComponents(String componentId, StormTopology topology) { Set<String> components = new HashSet<String>(); Map<String, Bolt> bolts = topology.get_bolts(); for (Entry<String, Bolt> entry : bolts.entrySet()) { String downstreamComponentId = entry.getKey(); Bolt bolt = entry.getValue(); Set<GlobalStreamId> input = bolt.get_common().get_inputs().keySet(); for (GlobalStreamId stream : input) { String upstreamComponentId = stream.get_componentId(); if (upstreamComponentId.equals(componentId)) { components.add(downstreamComponentId); break; } } } return components; } public static Set<String> getAllDownstreamComponents(String componentId, StormTopology topology) { return getAllDownstreamComponents(componentId, topology, new HashSet<String>()); } public static Set<String> getAllDownstreamComponents(String componentId, StormTopology topology, Set<String> traversedComponents) { Set<String> components = new HashSet<String>(); traversedComponents.add(componentId); Map<String, Bolt> bolts = topology.get_bolts(); for (Entry<String, Bolt> entry : bolts.entrySet()) { String downstreamComponentId = entry.getKey(); Bolt bolt = entry.getValue(); Set<GlobalStreamId> input = bolt.get_common().get_inputs().keySet(); for (GlobalStreamId stream : input) { String upstreamComponentId = stream.get_componentId(); if (upstreamComponentId.equals(componentId) && !traversedComponents.contains(downstreamComponentId)) { components.add(downstreamComponentId); components.addAll(getAllDownstreamComponents(downstreamComponentId, topology, traversedComponents)); break; } } } return components; } public static Set<Integer> getDownstreamTasks(String componentId, TopologyContext context) { Set<Integer> tasks = new HashSet<Integer>(); StormTopology topology = context.getRawTopology(); Map<String, Bolt> bolts = topology.get_bolts(); for (Entry<String, Bolt> entry : bolts.entrySet()) { String downstreamComponentId = entry.getKey(); Bolt bolt = entry.getValue(); Set<GlobalStreamId> input = bolt.get_common().get_inputs().keySet(); for (GlobalStreamId stream : input) { String upstreamComponentId = stream.get_componentId(); if (upstreamComponentId.equals(componentId)) { tasks.addAll(context.getComponentTasks(downstreamComponentId)); break; } } } return tasks; } public static Set<String> getUpstreamSpouts(String componentId, TopologyContext context) { Set<String> spoutIds = new HashSet<String>(); StormTopology topology = context.getRawTopology(); Map<String, SpoutSpec> spouts = topology.get_spouts(); for (Entry<String, SpoutSpec> entry : spouts.entrySet()) { String spoutId = entry.getKey(); Set<String> downstreamComponentIds = getAllDownstreamComponents(spoutId, context.getRawTopology()); if (downstreamComponentIds.contains(componentId)) { spoutIds.add(spoutId); } } return spoutIds; } public static Set<String> getUpstreamComponents(String componentId, TopologyContext context) { Set<String> upstreamComponents = new HashSet<String>(); ComponentCommon componentCommon = Utils.getComponentCommon(context.getRawTopology(), componentId); Set<GlobalStreamId> input = componentCommon.get_inputs().keySet(); for (GlobalStreamId stream : input) { upstreamComponents.add(stream.get_componentId()); } return upstreamComponents; } public static Set<Integer> getUpstreamTasks(String componentId, TopologyContext context) { Set<String> upstreamComponents = getUpstreamComponents(componentId, context); return new HashSet<Integer>(context.getComponentsTasks(upstreamComponents)); } public static Set<String> getInputStreamIds(TopologyContext context) { Set<String> ret = new HashSet<String>(); Set<GlobalStreamId> inputs = context.getThisSources().keySet(); for (GlobalStreamId streamId : inputs) { ret.add(streamId.get_streamId()); } return ret; } public static boolean isUserDefStream(String streamName) { return !streamName.equals(BARRIER_STREAM_ID); } public static long nextTransactionBatchId(long batchId) { return ++batchId; } public static int groupIndex(StormTopology topology, String spoutName) { Set<String> spoutComponents = topology.get_spouts().keySet(); return groupIds(spoutComponents).get(spoutName); } public static Map<String, Integer> groupIds(Set<String> names) { Collections.sort(new ArrayList<String>(names)); Map<String, Integer> ret = new HashMap<String, Integer>(); int i = 1; for (String name : names) { ret.put(name, i); i++; } return ret; } public static Set<String> getStatefulBolts(StormTopology topology) { Set<String> statefulBolts = new HashSet<String>(); Map<String, Bolt> bolts = topology.get_bolts(); for (Entry<String, Bolt> entry : bolts.entrySet()) { Bolt bolt = entry.getValue(); Map conf = JStormUtils.parseJson(bolt.get_common().get_json_conf()); if (JStormUtils.parseBoolean(conf.get(TRANSACTION_STATEFUL_BOLT), false)) { statefulBolts.add(entry.getKey()); } } return statefulBolts; } public static Set<String> getEndBolts(StormTopology topology, String sourceId) { Set<String> endBolts = new HashSet<String>(); Map<String, Bolt> bolts = topology.get_bolts(); for (Entry<String, Bolt> entry : bolts.entrySet()) { Bolt bolt = entry.getValue(); Map<String, StreamInfo> outputStreams = bolt.get_common().get_streams(); if (outputStreams.size() == 0) { endBolts.add(entry.getKey()); } } return endBolts; } }