use of co.cask.cdap.data2.transaction.queue.QueueEntryRow in project cdap by caskdata.
the class InMemoryQueue method dequeue.
public ImmutablePair<List<Key>, List<byte[]>> dequeue(Transaction tx, ConsumerConfig config, ConsumerState consumerState, int maxBatchSize) {
List<Key> keys = Lists.newArrayListWithCapacity(maxBatchSize);
List<byte[]> datas = Lists.newArrayListWithCapacity(maxBatchSize);
NavigableSet<Key> keysToScan = consumerState.startKey == null ? entries.navigableKeySet() : entries.tailMap(consumerState.startKey).navigableKeySet();
boolean updateStartKey = true;
// navigableKeySet is immune to concurrent modification
for (Key key : keysToScan) {
if (keys.size() >= maxBatchSize) {
break;
}
if (updateStartKey && key.txId < tx.getFirstShortInProgress()) {
// See QueueEntryRow#canCommit for reason.
consumerState.startKey = key;
}
if (tx.getReadPointer() < key.txId) {
// the entry is newer than the current transaction. so are all subsequent entries. bail out.
break;
} else if (tx.isInProgress(key.txId)) {
// the entry is in the exclude list of current transaction. There is a chance that visible entries follow.
// next time we have to revisit this entry
updateStartKey = false;
continue;
}
Item item = entries.get(key);
if (item == null) {
// entry was deleted (evicted or undone) after we started iterating
continue;
}
// check whether this is processed already
ConsumerEntryState state = item.getConsumerState(config.getGroupId());
if (ConsumerEntryState.PROCESSED.equals(state)) {
// already processed but not yet evicted. move on
continue;
}
if (config.getDequeueStrategy().equals(DequeueStrategy.FIFO)) {
// for FIFO, attempt to claim the entry and return it
if (item.claim(config)) {
keys.add(key);
datas.add(item.entry.getData());
}
// else: someone else claimed it, or it was already processed, move on, but we may have to revisit this.
updateStartKey = false;
continue;
}
// for hash/round robin, if group size is 1, just take it
if (config.getGroupSize() == 1) {
keys.add(key);
datas.add(item.entry.getData());
updateStartKey = false;
continue;
}
// hash by entry hash key or entry id
int hash;
if (config.getDequeueStrategy().equals(DequeueStrategy.ROUND_ROBIN)) {
hash = key.hashCode();
} else {
Integer hashFoundInEntry = item.entry.getHashKey(config.getHashKey());
hash = hashFoundInEntry == null ? 0 : hashFoundInEntry;
}
// modulo of a negative is negative, make sure we're positive or 0.
if (Math.abs(hash) % config.getGroupSize() == config.getInstanceId()) {
keys.add(key);
datas.add(item.entry.getData());
updateStartKey = false;
}
}
return keys.isEmpty() ? null : ImmutablePair.of(keys, datas);
}
Aggregations