package com.alimama.mdrillImport; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.log4j.Logger; import com.alipay.bluewhale.core.utils.StormUtils; import backtype.storm.spout.SpoutOutputCollector; import backtype.storm.task.TopologyContext; import backtype.storm.topology.IRichSpout; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.tuple.Fields; public class ImportSpout implements IRichSpout{ private static Logger LOG = Logger.getLogger(ImportSpout.class); private static final long serialVersionUID = 1L; private SpoutOutputCollector collector; private ImportReader reader=null; private DataParser parse=null; private String confPrefix; public ImportSpout(String confPrefix) { this.confPrefix=confPrefix; } int buffersize=5000; int intMapsize=500; @Override public void open(Map conf, TopologyContext context,SpoutOutputCollector collector) { try { parse=(DataParser) Class.forName(String.valueOf(conf.get(this.confPrefix+"-parse"))).newInstance(); parse.init(true, conf, context); } catch (Throwable e1) { LOG.error("DataParser",e1); } int timeout=Integer.parseInt(String.valueOf(conf.get(confPrefix+"-timeoutSpout"))); this.buffersize=Integer.parseInt(String.valueOf(conf.get(confPrefix+"-spoutbuffer"))); Object chkIntervel=conf.get(confPrefix+"-spoutIntervel"); if(chkIntervel!=null) { this.checkIntervel=Integer.parseInt(String.valueOf(chkIntervel)); } this.timeoutCheck=new TimeOutCheck(timeout*1000l); this.status=new SpoutStatus(); this.collector = collector; int readerCount=context.getComponentTasks(context.getThisComponentId()).size(); int readerIndex=context.getThisTaskIndex(); this.intMapsize=Math.min(this.buffersize, 1024); nolockbuffer=new HashMap<BoltStatKey, BoltStatVal>(this.intMapsize); try { this.reader=new ImportReader(conf, confPrefix, parse, readerIndex, readerCount); } catch (IOException e) { LOG.error("TTReader",e); } } private HashMap<BoltStatKey, BoltStatVal> nolockbuffer=null; private SpoutStatus status=null; private TimeOutCheck timeoutCheck=null; private static SimpleDateFormat formatHour = new SimpleDateFormat("HH:mm:ss"); int checkIntervel=1000; private boolean putdata(DataParser.DataIter log) { long ts=log.getTs(); BoltStatKey key=new BoltStatKey(log.getGroup()); BoltStatVal val=new BoltStatVal(log.getSum(),ts); BoltStatVal statval=nolockbuffer.get(key); this.status.ttInput++; if(statval==null) { nolockbuffer.put(key, val); this.status.groupCreate++; }else{ statval.merger(val); } if((this.status.ttInput%this.checkIntervel!=0)) { return false; } if(!this.timeoutCheck.istimeout()&&nolockbuffer.size()<buffersize) { return false; } this.timeoutCheck.reset(); HashMap<BoltStatKey, BoltStatVal> buffer=nolockbuffer; LOG.info(this.confPrefix+"####total:group="+buffer.size()+",ts:"+formatHour.format(new Date(ts))+",status:"+this.status.toString()); nolockbuffer=new HashMap<BoltStatKey, BoltStatVal>(this.intMapsize); int batch=1; for(Entry<BoltStatKey, BoltStatVal> e:buffer.entrySet()) { batch++; BoltStatKey pkey=e.getKey(); BoltStatVal pvalue=e.getValue(); List<Object> data = StormUtils.mk_list((Object)pkey,pvalue); collector.emit(data, SpoutUtils.uuid()); if(batch%50==0) { this.sleep(10); } } if(this.status.ttInput>100000000) { this.status.reset(); } return true; } @Override public synchronized void nextTuple() { try { List ttdata = this.reader.read(); if(ttdata==null) { return ; } for(Object o:ttdata) { this.status.ttInput++; DataParser.DataIter pv=(DataParser.DataIter)o; while(true) { this.status.groupInput++; this.putdata(pv); if(!pv.next()) { break; } } } } catch (Throwable e) { this.sleep(100); } } private void sleep(int i) { try { Thread.sleep(i); } catch (InterruptedException e1) { } } @Override public void close() { } @Override public void ack(Object msgId) { this.status.ackCnt++; } @Override public void fail(Object msgId) { this.status.failCnt++; } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("key","value")); } @Override public Map<String, Object> getComponentConfiguration() { Map<String, Object> rtnmap = new HashMap<String, Object>(); return rtnmap; } }