/*******************************************************************************
* Copyright © 2012-2015 eBay Software Foundation
* This program is dual licensed under the MIT and Apache 2.0 licenses.
* Please see LICENSE for more information.
*******************************************************************************/
package com.ebay.jetstream.batcher;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author shmurthy@ebay.com - This is a generic batcher that batches data items of the specified type and flushes the batch of data items. The flush is triggered when
* the batch queue contains items equal to the specified threshold or the flush timer fires. The threshold and flush timer interval are both
* configurable.
*/
public abstract class AutoFlushBatcher<T> implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger("com.ebay.jetstream.messaging");
private AtomicInteger m_flushInterval = new AtomicInteger(100);
private AtomicInteger m_maxFlushSz = new AtomicInteger(40);
private AutoFlushWriterQueue m_queue;
private Thread m_batchAssembler;
private AtomicBoolean m_shutdown = new AtomicBoolean(false);
private int m_maxQueueSz = 100000;
private int m_waitBetweenFlush = 30; // in millis - default = 30 millis
public int getWaitBetweenFlush() {
return m_waitBetweenFlush;
}
public void setWaitBetweenFlush(int waitBetweenFlush) {
m_waitBetweenFlush = waitBetweenFlush;
}
public int getMaxQueueSz() {
return m_maxQueueSz;
}
public void setMaxQueueSz(int maxQueueSz) {
m_maxQueueSz = maxQueueSz;
}
public int getFlushInterval() {
return m_flushInterval.get();
}
public void setFlushInterval(int flushInterval) {
m_flushInterval.set(flushInterval);
}
public void start() {
m_batchAssembler = new Thread(this, "BatchAssemblerThread");
m_batchAssembler.start();
}
/**
* @return
*/
public int getMaxFlushSz() {
return m_maxFlushSz.get();
}
/**
* @param maxFlushSz
*/
public void setMaxFlushSz(int maxFlushSz) {
this.m_maxFlushSz.set(maxFlushSz);
}
/**
*
*/
public AutoFlushBatcher() {
m_queue = new AutoFlushWriterQueue<T>();
m_queue.setMaxFlushSz(m_maxFlushSz.get());
start();
}
/**
* @param autoFlushSz
* @param flushInterval
* in millis
*/
public AutoFlushBatcher(int autoFlushSz, int flushInterval) {
m_maxFlushSz.set(autoFlushSz);
m_flushInterval.set(flushInterval);
m_queue = new AutoFlushWriterQueue<T>();
m_queue.setMaxFlushSz(m_maxFlushSz.get());
start();
}
/**
* @param e
*/
public void write(T e) throws Exception {
if (m_shutdown.get())
throw new Exception("Batcher has been shutdown");
m_queue.add(e);
}
/**
* @param items
* - derived class to implement this method
*/
public abstract void flush(List<T> items);
/**
*
*/
public void shutdown() {
m_shutdown.set(true);
LOGGER.info( "Shutting down AutoFlushBufferWriter");
while (m_queue.size() > 0) {
List<T> events = m_queue.get(getMaxFlushSz());
if (events != null)
flush(events);
}
}
@Override
public void run() {
while (!m_shutdown.get()) {
long elapsedTime = System.currentTimeMillis()
- m_queue.getLastFlushTime();
if (m_queue.isTimeToFlush()
|| (elapsedTime > m_flushInterval.get())) {
m_queue.setLastFlushTime(System.currentTimeMillis());
List<T> events = m_queue.get(getMaxFlushSz());
if (events == null)
continue;
flush(events);
} else {
try {
Thread.sleep(getWaitBetweenFlush()); // wait 30 millis
} catch (InterruptedException e) {
}
}
}
}
}