/* * #! * % * Copyright (C) 2014 - 2016 Humboldt-Universität zu Berlin * % * Licensed 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 storm.lrb.bolt; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import storm.lrb.TopologyControlOld; import storm.lrb.model.SegmentStatistics; 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 de.hub.cs.dbis.lrb.queries.utils.TopologyControl; import de.hub.cs.dbis.lrb.types.PositionReport; import de.hub.cs.dbis.lrb.types.util.SegmentIdentifier; import de.hub.cs.dbis.lrb.util.Time; /** * This bolt computes the average speed of all cars in a given segment and direction and emits these every minute. * * This is the alternative to using AvgsBolt+LavBolt. * */ public class SegmentStatsBolt extends BaseRichBolt { private static final long serialVersionUID = 5537727428628598519L; private static final Logger LOG = LoggerFactory.getLogger(SegmentStatsBolt.class); private static final int START_MINUTE = 0; private static final int AVERAGE_MINS = 5; /** * contains all statistical information for each segment and minute */ private final SegmentStatistics segmentStats = new SegmentStatistics(); private OutputCollector collector; /* * internal implementation notes: - needs to be long because is unsed for list index access later */ private int curMinute = 0; private String tmpname; public SegmentStatsBolt() {} @Override public String toString() { return "SegmentStats [segmentStats=" + this.segmentStats + ", curMinute=" + this.curMinute + "]"; } @Override public void prepare(@SuppressWarnings("rawtypes") Map stormConf, TopologyContext context, OutputCollector collector) { this.collector = collector; this.tmpname = context.getThisComponentId() + context.getThisTaskId(); LOG.info(this.tmpname + " mit diesen sources: " + context.getThisSources().keySet().toString()); } @Override public void execute(Tuple tuple) { this.countAndAck(tuple); } private void emitCurrentWindowCounts() { long prevMinute = Math.max(this.curMinute - 1, START_MINUTE); Set<SegmentIdentifier> segmentList = this.segmentStats.getXsdList(); if(LOG.isDebugEnabled()) { LOG.debug("Watching the following segments: %s", segmentList); } // compute the current lav for every segment for(SegmentIdentifier xsd : segmentList) { int segmentCarCount = 0; double speedSum = 0.0; int time = Math.max(this.curMinute - AVERAGE_MINS, 1); for(; time <= this.curMinute; ++time) { if(this.segmentStats.vehicleCount(time, xsd) > 0) { segmentCarCount++; speedSum += this.segmentStats.speedAverage(time, xsd); } } double speedAverage = 0.0; if(segmentCarCount != 0) { speedAverage = (speedSum / segmentCarCount); } this.collector.emit(new Values(xsd.getXWay(), xsd.getSegment(), xsd.getDirection(), segmentCarCount, speedAverage, prevMinute)); } } private void countAndAck(Tuple tuple) { PositionReport pos = (PositionReport)tuple.getValueByField(TopologyControlOld.POS_REPORT_FIELD_NAME); SegmentIdentifier segment = null;// new SegmentIdentifier(pos); long newMinute = Time.getMinute(pos.getTime()); if(newMinute > this.curMinute) { this.emitCurrentWindowCounts(); this.curMinute = Time.getMinute(pos.getTime()); } this.segmentStats.addVehicleSpeed(this.curMinute, segment, pos.getVid(), pos.getSpeed()); this.collector.ack(tuple); } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields(TopologyControl.XWAY_FIELD_NAME, TopologyControl.SEGMENT_FIELD_NAME, TopologyControl.DIRECTION_FIELD_NAME, TopologyControl.CAR_COUNT_FIELD_NAME, TopologyControl.LAST_AVERAGE_SPEED_FIELD_NAME, TopologyControl.MINUTE_FIELD_NAME)); } }