package com.realtimecep.storm.starter.trident;
import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.LocalDRPC;
import backtype.storm.generated.StormTopology;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
import storm.trident.TridentTopology;
import storm.trident.operation.BaseFunction;
import storm.trident.operation.TridentCollector;
import storm.trident.tuple.TridentTuple;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* 배치 단위로 데이터를 처리하는 기능을 테스트하기 위한 클래스.
*
* @author tedwon
*/
public class MyTridentWordCountBatch {
public static class Split extends BaseFunction {
@Override
public void execute(TridentTuple tuple, TridentCollector collector) {
String sentence = tuple.getString(0);
// System.out.println(sentence);
MyEvent event = new MyEvent(sentence);
collector.emit(new Values(event.getData5(), event));
}
}
public static class Split2 extends BaseFunction {
// 맵안에 채널 별 맵을 가진다.
// key: channel
// vale: (
// key: id + start time
// value: current time
// )
private Map<String, Map<String, String>> ratingData = Collections.synchronizedSortedMap(new ConcurrentSkipListMap<String, Map<String, String>>());
@Override
public void execute(TridentTuple tuple, TridentCollector collector) {
String channel = tuple.getStringByField("channel");
MyEvent event = (MyEvent) tuple.getValueByField("word");
String startOrStop = event.getData2();
Map<String, String> channelData = null;
// 시작이면,
// map에 put
String key = event.getData1() + "-" + event.getData3();
if ("start".equalsIgnoreCase(startOrStop)) {
if (ratingData.get(channel) == null) {
// 처음이면 채널 맵 생성
channelData = Collections.synchronizedSortedMap(new ConcurrentSkipListMap<String, String>());
} else {
// 처널 맵에 시청 시작 데이터 추가
channelData = ratingData.get(channel);
}
channelData.put(key, event.getData4());
ratingData.put(channel, channelData);
} else {
// 시청 종료이면,
// map에 remove
channelData = ratingData.get(channel);
if (channelData != null) {
channelData.remove(key);
}
// apply updated data
ratingData.put(channel, channelData);
}
System.out.println("!### " + channel + " : " + ratingData.get(channel).size());
}
}
public static StormTopology buildTopology(LocalDRPC drpc) {
MyFixedBatchSpout spout = new MyFixedBatchSpout(new Fields("sentence"), 2,
new Values("1,start,2013-01-01 00:00:00,2013-01-01 00:00:10,11"),
new Values("4,start,2013-01-01 00:00:00,2013-01-01 00:00:10,7"),
new Values("2,start,2013-01-01 00:00:01,2013-01-01 00:00:11,11"),
new Values("5,start,2013-01-01 00:00:01,2013-01-01 00:00:11,7"),
new Values("3,start,2013-01-01 00:00:02,2013-01-01 00:00:12,11"),
new Values("6,start,2013-01-01 00:00:02,2013-01-01 00:00:12,7"),
new Values("1,stop,2013-01-01 00:00:00,2013-01-01 00:01:10,11"),
new Values("4,stop,2013-01-01 00:00:00,2013-01-01 00:01:10,7"),
new Values("2,stop,2013-01-01 00:00:01,2013-01-01 00:01:11,11"),
new Values("5,stop,2013-01-01 00:00:01,2013-01-01 00:01:11,7"),
new Values("3,stop,2013-01-01 00:00:02,2013-01-01 00:01:12,11"),
new Values("6,stop,2013-01-01 00:00:02,2013-01-01 00:01:12,7")
);
spout.setCycle(false);
TridentTopology topology = new TridentTopology();
topology.newStream("spout1", spout)
.parallelismHint(2)
.each(new Fields("sentence"), new Split(), new Fields("channel", "word"))
.groupBy(new Fields("channel"))
.each(new Fields("channel", "word"), new Split2(), new Fields("myword"));
return topology.build();
}
public static void main(String[] args) {
Config conf = new Config();
conf.setMaxSpoutPending(20);
conf.put(Config.TOPOLOGY_WORKER_CHILDOPTS, "-Xmx2g");
LocalCluster cluster = new LocalCluster();
LocalDRPC drpc = new LocalDRPC();
// cluster.submitTopology("wordCounter", conf, buildTopology(drpc));
cluster.submitTopology("wordCounter", conf, buildTopology(null));
// drpc.shutdown();
// cluster.shutdown();
}
}