package storm.emq;
import backtype.storm.Config;
import backtype.storm.spout.ISpout;
import backtype.storm.spout.ISpoutOutputCollector;
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.topology.base.BaseRichSpout;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by jiasheng on 15-12-30.
*/
public class MockSpoutExecutor {
private final ISpout spout;
private final AtomicLong emitCount = new AtomicLong();
private final AtomicLong ackCount = new AtomicLong();
private final AtomicLong failCount = new AtomicLong();
private final Random random = new Random();
private volatile boolean running = true;
public MockSpoutExecutor(ISpout spout) {
this.spout = spout;
}
public void exec() {
Map conf = new HashMap();
final LinkedBlockingQueue<String> emitedMessages = new LinkedBlockingQueue<String>();
conf.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 20);
spout.open(conf, null, new SpoutOutputCollector(new ISpoutOutputCollector() {
@Override
public List<Integer> emit(String s, List<Object> list, Object o) {
try {
emitedMessages.put(o.toString());
emitCount.incrementAndGet();
} catch (InterruptedException e) {
}
return null;
}
@Override
public void emitDirect(int i, String s, List<Object> list, Object o) {
}
@Override
public void reportError(Throwable throwable) {
}
}));
//do work
while (running) {
spout.nextTuple();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
if (emitedMessages.isEmpty() && emitCount.get() != 0)
this.stop();
String message = null;
while ((message = emitedMessages.poll()) != null) {
if (random.nextInt(100) > 95) {
spout.fail(message);
failCount.incrementAndGet();
} else {
spout.ack(message);
ackCount.incrementAndGet();
}
}
}
}
public long getEmitCount() {
return emitCount.get();
}
public long getAckCount() {
return ackCount.get();
}
public long getFailCount() {
return failCount.get();
}
public void stop() {
spout.close();
running = false;
}
}