/* * #! * % * 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; import storm.lrb.TopologyControlOld; import storm.lrb.tools.Helper; 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 backtype.storm.utils.Utils; import de.hub.cs.dbis.lrb.queries.utils.TopologyControl; import de.hub.cs.dbis.lrb.toll.TollDataStore; import de.hub.cs.dbis.lrb.types.AbstractLRBTuple; import de.hub.cs.dbis.lrb.types.DailyExpenditureRequest; /** * Stub for daily expenditure queries. Responds to {@link DailyExpenditureRequest}s with tuple in the form of (Type = 3, * Time (specifying the time that d was emitted), Emit (specifying the time the query response is emitted), QID * (identifying the query that issued the request), Bal (the sum of all tolls from expressway x on day n that were * charged to the vehi- cle’s account). Reads from {@link TopologyControl#DAILY_EXPEDITURE_REQUESTS_STREAM_ID} and emits * tuple on {@link Utils#DEFAULT_STREAM_ID}. * * @TODO either use external distributed database to keep historic data or load it into memory * */ public class DailyExpenditureBolt extends BaseRichBolt { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(DailyExpenditureBolt.class); private transient TollDataStore dataStore; private OutputCollector collector; /** * */ public DailyExpenditureBolt() {} public TollDataStore getDataStore() { return this.dataStore; } /** * initializes the used {@link TollDataStore} using the string specified as value to the * {@link Helper#TOLL_DATA_STORE_CONF_KEY} map key. * * @param conf * @param context * @param collector */ /* * internal implementation notes: - due to the fact that storm is incapable of serializing Class property, a String * has to be passed in conf */ @Override public void prepare(@SuppressWarnings("rawtypes") Map conf, TopologyContext context, OutputCollector collector) { this.collector = collector; String tollDataStoreClass = (String)conf.get(Helper.TOLL_DATA_STORE_CONF_KEY); try { this.dataStore = (TollDataStore)Class.forName(tollDataStoreClass).newInstance(); } catch(InstantiationException ex) { throw new RuntimeException(String.format("The data store instance '%s' could not be initialized (see " + "nested exception for details)", this.dataStore), ex); } catch(IllegalAccessException ex) { throw new RuntimeException(String.format("The data store instance '%s' could not be initialized (see " + "nested exception for details)", this.dataStore), ex); } catch(ClassNotFoundException ex) { throw new RuntimeException(String.format("The data store instance '%s' could not be initialized (see " + "nested exception for details)", this.dataStore), ex); } } @Override public void execute(Tuple tuple) { Fields fields = tuple.getFields(); if(fields.contains(TopologyControlOld.DAILY_EXPEDITURE_REQUEST_FIELD_NAME)) { DailyExpenditureRequest exp = (DailyExpenditureRequest)tuple .getValueByField(TopologyControlOld.DAILY_EXPEDITURE_REQUEST_FIELD_NAME); int vehicleIdentifier = exp.getVid(); Values values; Integer toll = this.dataStore.retrieveToll(exp.getXWay(), exp.getDay(), vehicleIdentifier); if(toll != null) { LOG.debug("ExpenditureRequest: found vehicle identifier %d", vehicleIdentifier); // LOG.debug("3, %d, %d, %d, %d", exp.getTime(), exp.getTimer().getOffset(), exp.getQueryIdentifier(), // toll); values = new Values(AbstractLRBTuple.DAILY_EXPENDITURE_REQUEST, exp.getTime(), exp.getQid(), toll); } else { values = new Values(AbstractLRBTuple.DAILY_EXPENDITURE_REQUEST, exp.getTime(), exp.getQid(), 20); // initial // toll: // 20 } this.collector.emit(values); } this.collector.ack(tuple); } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields(TopologyControlOld.EXPEDITURE_NOTIFICATION_FIELD_NAME)); } }