package org.yamcs.yarch.rocksdb;
import org.rocksdb.RocksIterator;
import org.yamcs.utils.ByteArrayUtils;
/**
* wrapper around a rocksdb iterator that only supports next() and is restricted to a range.
*
* if strictStart=true
* then the first rangeStart.length bytes of the key are compared with the rangeStart, if they are equal the record is skipped.
* same is valid for strictEnd
*
* So with the following DB:
* 1: 0x00 0x00 0x00 0x02
* 2: 0x01 0x01 0x01 0x00
* 3: 0x01 0x01 0x01 0x03
* 4: 0x01 0x01 0x02 0x00
*
* and rangeStart = 0x01 0x01 0x01, strictStart=true
*
* the iterator will skip records 1,2 and 3 and start from record 4
*
*
* @author nm
*
*/
public class AscendingRangeIterator implements DbIterator {
final RocksIterator iterator;
final byte[] rangeStart;
final boolean strictStart;
final byte[] rangeEnd;
final boolean strictEnd;
boolean valid = false;
private byte[] curKey;
public AscendingRangeIterator(RocksIterator it, byte[] rangeStart, boolean strictStart, byte[] rangeEnd, boolean strictEnd) {
this.iterator = it;
this.rangeStart = rangeStart;
this.rangeEnd = rangeEnd;
this.strictStart = strictStart;
this.strictEnd = strictEnd;
init();
}
private void init() {
boolean startFound = false;
valid = false;
if(rangeStart==null) {
iterator.seekToFirst();
if(iterator.isValid()) {
curKey = iterator.key();
startFound = true;
}
} else {
iterator.seek(rangeStart);
if(iterator.isValid()) {
curKey = iterator.key();
if(strictStart && ByteArrayUtils.startsWith(curKey, rangeStart)) {
iterator.next();
if(iterator.isValid()) {
curKey = iterator.key();
startFound = true;
}
} else {
startFound = true;
}
}
}
if(startFound) {
//check that it is not beyond the end
if(rangeEnd!=null) {
int c = ByteArrayUtils.compare(curKey, rangeEnd);
if((strictEnd && c<0) || (c<=0)) {
valid = true;
}
} else {
valid = true;
}
}
}
@Override
public boolean isValid() {
return valid;
}
@Override
public void next() {
if(!valid) {
throw new IllegalStateException("iterator is not valid");
}
iterator.next();
if(iterator.isValid()) {
curKey = iterator.key();
if(rangeEnd!=null) {
int c = ByteArrayUtils.compare(curKey, rangeEnd);
if((strictEnd && c>=0) || (c>0)) {
valid = false;
}
}
} else {
valid = false;
}
}
public byte[] key() {
if(!valid) {
throw new IllegalStateException("iterator is not valid");
}
return curKey;
}
public byte[] value() {
if(!valid) {
throw new IllegalStateException("iterator is not valid");
}
return iterator.value();
}
@Override
public void close() {
valid = false;
iterator.close();
}
@Override
public void prev() {
throw new UnsupportedOperationException("this is an ascending iterator");
}
}