com.questdb.iter.JournalConcurrentIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of questdb-core Show documentation
Show all versions of questdb-core Show documentation
QuestDB is High Performance Time Series Database
/*******************************************************************************
* ___ _ ____ ____
* / _ \ _ _ ___ ___| |_| _ \| __ )
* | | | | | | |/ _ \/ __| __| | | | _ \
* | |_| | |_| | __/\__ \ |_| |_| | |_) |
* \__\_\\__,_|\___||___/\__|____/|____/
*
* Copyright (C) 2014-2016 Appsicle
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
******************************************************************************/
package com.questdb.iter;
import com.questdb.Journal;
import com.questdb.ex.JournalException;
import com.questdb.ex.JournalRuntimeException;
import com.questdb.misc.NamedDaemonThreadFactory;
import com.questdb.misc.Rows;
import com.questdb.mp.RingQueue;
import com.questdb.mp.SCSequence;
import com.questdb.mp.SPSequence;
import com.questdb.mp.Sequence;
import com.questdb.std.ObjList;
import com.questdb.std.ObjectFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class JournalConcurrentIterator extends com.questdb.std.AbstractImmutableIterator
implements ObjectFactory>, ConcurrentIterator {
private final Journal journal;
private final ObjList ranges;
private final ExecutorService service;
private RingQueue> buffer;
private Sequence pubSeq;
private Sequence subSeq;
private int bufferSize;
private boolean started = false;
private long cursor = -1;
public JournalConcurrentIterator(Journal journal, ObjList ranges, int bufferSize) {
this.bufferSize = bufferSize;
this.service = Executors.newSingleThreadExecutor(new NamedDaemonThreadFactory("questdb-iterator", false));
this.journal = journal;
this.ranges = ranges;
}
@Override
public ConcurrentIterator buffer(int bufferSize) {
this.bufferSize = bufferSize;
return this;
}
@Override
public void close() {
service.shutdown();
}
@Override
public Journal getJournal() {
return journal;
}
@Override
public boolean hasNext() {
if (!started) {
start();
started = true;
}
if (cursor >= 0) {
subSeq.done(cursor);
}
this.cursor = subSeq.nextBully();
return buffer.get(cursor).hasNext;
}
@Override
public T next() {
return buffer.get(cursor).object;
}
@Override
public Holder newInstance() {
Holder h = new Holder<>();
h.object = getJournal().newObject();
h.hasNext = true;
return h;
}
private Runnable getRunnable() {
return new Runnable() {
boolean hasNext = true;
private int currentIndex = 0;
private long currentRowID;
private long currentUpperBound;
private int currentPartitionID;
@Override
public void run() {
updateVariables();
while (true) {
try {
long cursor = pubSeq.nextBully();
Holder holder = buffer.get(cursor);
boolean hadNext = hasNext;
if (hadNext) {
journal.read(Rows.toRowID(currentPartitionID, currentRowID), holder.object);
if (currentRowID < currentUpperBound) {
currentRowID++;
} else {
currentIndex++;
updateVariables();
}
}
holder.hasNext = hadNext;
pubSeq.done(cursor);
if (!hadNext) {
break;
}
} catch (JournalException e) {
throw new JournalRuntimeException("Error in iterator [%s]", e, this);
}
}
}
private void updateVariables() {
if (currentIndex < ranges.size()) {
JournalIteratorRange w = ranges.getQuick(currentIndex);
currentRowID = w.lo;
currentUpperBound = w.hi;
currentPartitionID = w.partitionID;
} else {
hasNext = false;
}
}
};
}
private void start() {
this.buffer = new RingQueue<>(this, bufferSize);
this.pubSeq = new SPSequence(bufferSize);
this.subSeq = new SCSequence();
this.pubSeq.then(subSeq).then(pubSeq);
service.submit(getRunnable());
}
protected final static class Holder {
T object;
boolean hasNext;
}
}