move TimeStampDeltaDecoder to BSFile
Now the encoding and decoding code is in the same class.
This commit is contained in:
@@ -6,6 +6,7 @@ import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@@ -37,11 +38,30 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class BSFile implements AutoCloseable {
|
||||
|
||||
private static class TimeStampDeltaDecoder implements Function<LongList, LongList> {
|
||||
|
||||
/**
|
||||
* Computes the inverse of the delta encoding in {@link BSFile#appendTimeValue}
|
||||
*/
|
||||
@Override
|
||||
public LongList apply(final LongList t) {
|
||||
long lastTimeValue = 0;
|
||||
for (int i = 0; i < t.size(); i += 2) {
|
||||
lastTimeValue += t.get(i);
|
||||
t.set(i, lastTimeValue);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BSFile.class);
|
||||
|
||||
private static final ThreadLocal<LongSequenceEncoderDecoder> INT_ENCODER = ThreadLocal
|
||||
.withInitial(LongSequenceEncoderDecoder::new);
|
||||
|
||||
private static final TimeStampDeltaDecoder TIME_DELTA_DECODER = new TimeStampDeltaDecoder();
|
||||
|
||||
/*
|
||||
* The last disk block of this sequence. This is the block new values will be
|
||||
* appended to.
|
||||
@@ -78,9 +98,32 @@ public class BSFile implements AutoCloseable {
|
||||
buffer = diskStorage.getDiskBlock(lastBlockNumber);
|
||||
}
|
||||
offsetInBuffer = determineWriteOffsetInExistingBuffer(buffer);
|
||||
lastEpochMilli = determineLastEpochMilli(buffer);
|
||||
LOGGER.trace("create bsFile={} lastBlockNumber={}", rootBlockNumber, lastBlockNumber);
|
||||
}
|
||||
|
||||
private long determineLastEpochMilli(final DiskBlock diskBlock) {
|
||||
|
||||
LongList longList = new LongList();
|
||||
|
||||
// get the time/value delta encoded longs
|
||||
final byte[] buf = diskBlock.getBuffer();
|
||||
INT_ENCODER.get().decodeInto(buf, longList);
|
||||
final long result;
|
||||
if (longList.isEmpty()) {
|
||||
// only new files have empty disk blocks
|
||||
// and empty disk blocks have time offset 0
|
||||
result = 0;
|
||||
} else {
|
||||
// decode the deltas to get the correct timestamps
|
||||
longList = TIME_DELTA_DECODER.apply(longList);
|
||||
|
||||
// return the last timestamp
|
||||
result = longList.get(longList.size() - 2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int determineWriteOffsetInExistingBuffer(final DiskBlock buffer) {
|
||||
|
||||
final byte[] buf = buffer.getBuffer();
|
||||
@@ -106,9 +149,9 @@ public class BSFile implements AutoCloseable {
|
||||
public void appendTimeValue(final long epochMilli, final long value) throws IOException {
|
||||
final LongSequenceEncoderDecoder intEncoder = INT_ENCODER.get();
|
||||
|
||||
final long epochMilliDiff = epochMilli - lastEpochMilli;
|
||||
final long epochMilliDelta = epochMilli - lastEpochMilli;
|
||||
|
||||
final int bytesWritten = intEncoder.encodeInto(epochMilliDiff, value, buffer.getBuffer(), offsetInBuffer);
|
||||
final int bytesWritten = intEncoder.encodeInto(epochMilliDelta, value, buffer.getBuffer(), offsetInBuffer);
|
||||
|
||||
if (bytesWritten == 0) {
|
||||
flushFullBufferAndCreateNew();
|
||||
@@ -194,6 +237,11 @@ public class BSFile implements AutoCloseable {
|
||||
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
|
||||
}
|
||||
|
||||
public Stream<LongList> streamOfTimeValueLongLists() {
|
||||
final Stream<LongList> stream = streamOfLongLists();
|
||||
return stream.map(TIME_DELTA_DECODER);
|
||||
}
|
||||
|
||||
private static class LongListIterator implements Iterator<LongList> {
|
||||
|
||||
private LongList next = null;
|
||||
@@ -239,6 +287,13 @@ public class BSFile implements AutoCloseable {
|
||||
return result;
|
||||
}
|
||||
|
||||
public LongList asTimeValueLongList() {
|
||||
|
||||
final LongList result = new LongList();
|
||||
streamOfTimeValueLongLists().forEachOrdered(result::addAll);
|
||||
return result;
|
||||
}
|
||||
|
||||
public long getRootBlockNumber() {
|
||||
|
||||
return rootBlockNumber;
|
||||
|
||||
Reference in New Issue
Block a user