package com.leansoft.bigqueue;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import com.leansoft.luxun.common.annotations.NotThreadSafe;
/**
* extension to FanOutQueue to expose write lock of the queue front
*
* @author bulldog
*
*/
public class FanOutQueueImplEx extends FanOutQueueImpl implements IFanOutQueueEx {
public FanOutQueueImplEx(String queueDir, String queueName)
throws IOException {
super(queueDir, queueName);
}
public FanOutQueueImplEx(String queueDir, String queueName, int pageSize) throws IOException {
super(queueDir, queueName, pageSize);
}
@Override
public Lock getQueueFrontWriteLock(String fanoutId) throws IOException {
return super.getQueueFront(fanoutId).writeLock;
}
@Override
public Lock getInnerArrayReadLock() {
return super.innerArray.arrayReadLock;
}
@Override
public int getNumberOfBackFiles() {
return super.innerArray.dataPageFactory.getBackPageFileSet().size();
}
// batch dequeue tailored for Luxun batch consuming
@NotThreadSafe
public BatchReadResult batchDequeue(String fanoutId, int maxFetchSize) throws IOException {
QueueFront qf = this.getQueueFront(fanoutId);
int totalFetchedSize = 0;
List<ByteBuffer> bufferList = new ArrayList<ByteBuffer>();
while (qf.index.get() != innerArray.arrayHeadIndex.get() && totalFetchedSize < maxFetchSize) {
int length = innerArray.getItemLength(qf.index.get());
if (totalFetchedSize + length > maxFetchSize) {
break;
}
byte[] data = null;
try {
data = innerArray.get(qf.index.get());
} catch (IndexOutOfBoundsException ex) {
// maybe the back array has just been truncated to limit size
qf.index.set(innerArray.arrayTailIndex.get());
data = innerArray.get(qf.index.get());
}
bufferList.add(ByteBuffer.wrap(data));
totalFetchedSize += length;
qf.index.incrementAndGet();
if (qf.index.longValue() < 0) {
qf.index.set(0); //wrap
}
}
if (bufferList.size() > 0) { // commit consuming
qf.persistIndex();
}
BatchReadResult result = new BatchReadResult();
result.bufferList = bufferList;
result.totalFetchedSize = totalFetchedSize;
return result;
}
public static class BatchReadResult {
public List<ByteBuffer> bufferList;
public int totalFetchedSize;
}
}