/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alipay.dw.jstorm.example.deploy; import backtype.storm.task.OutputCollector; import backtype.storm.task.TopologyContext; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.topology.base.BaseRichBolt; import backtype.storm.tuple.Fields; import backtype.storm.tuple.Tuple; import backtype.storm.tuple.Values; import com.alibaba.jstorm.client.ConfigExtension; import com.alibaba.jstorm.utils.JStormUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.Map; /** * @author JohnFang (xiaojian.fxj@alibaba-inc.com). */ public class DeployBolt extends BaseRichBolt { private final static Logger LOG = LoggerFactory.getLogger(DeployBolt.class); private OutputCollector _collector; private Map<String, List<Integer>> _sourceTasks; private Map<String, List<Integer>> _targetTasks; private volatile Integer _expectExcevieNum = 0; private Integer timeout; private TopologyContext context; public void prepare(Map conf, TopologyContext context, OutputCollector collector) { _collector = collector; _sourceTasks = context.getThisSourceComponentTasks(); _targetTasks = context.getThisTargetComponentTasks(); for (List<Integer> tasks : _sourceTasks.values()) { _expectExcevieNum += tasks.size(); } this.context = context; timeout = ConfigExtension.getTaskCleanupTimeoutSec(conf) / 2; LOG.info("this component's sourceTasks is {}, and the target tasks is {}", _sourceTasks, _targetTasks); } public void execute(Tuple tuple) { if (tuple.getValues().size() == 0) { _expectExcevieNum--; } else { JStormUtils.sleepMs(1); _collector.emit(tuple, new Values(tuple.getValues())); _collector.ack(tuple); } } public void cleanup() { if (JStormUtils.isKilledStatus(context)){ long start = System.currentTimeMillis(); while (_expectExcevieNum != 0) { if (_expectExcevieNum < 0) { LOG.warn("_expectExcevieNum can't less than zero"); break; } JStormUtils.sleepMs(1); if (System.currentTimeMillis() - start > timeout * 1000) { LOG.warn("timeout, this component still not receive {} finish stream", _expectExcevieNum); break; } } JStormUtils.sleepMs(10); int sendNum = 0; for (List<Integer> tasks : _targetTasks.values()) { for (Integer task : tasks) { sendNum++; _collector.emitDirect(task, new Values()); } } _collector.flush(); LOG.info("this component-{} already sent {} finish messages", context.getThisTaskId(), sendNum); JStormUtils.sleepMs(100); } } public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("message")); } }