package org.yamcs.parameterarchive; import org.rocksdb.RocksIterator; import org.yamcs.utils.DatabaseCorruptionException; import org.yamcs.utils.DecodingException; /** * Iterates over the segments of one partition for a parameter_id, ParameterGroup_id, between a start and stop * * @author nm * */ public class PartitionIterator { private final RocksIterator iterator; private boolean valid=false; private SegmentKey currentKey; private final int parameterId, parameterGroupId; private final long start, stop; private final boolean ascending; SegmentEncoderDecoder segmentEncoder = new SegmentEncoderDecoder(); private byte[] currentEngValueSegment; private byte[] currentRawValueSegment; private byte[] currentStatusSegment; final boolean retrieveEngValue; final boolean retrieveRawValue; final boolean retrieveParameterStatus; public PartitionIterator(RocksIterator iterator, int parameterId, int parameterGroupId, long start, long stop, boolean ascending, boolean retrieveEngValue, boolean retrieveRawValue, boolean retrieveParameterStatus) { this.parameterId = parameterId; this.parameterGroupId = parameterGroupId; this.start = start; this.stop = stop; this.ascending = ascending; this.retrieveEngValue = retrieveEngValue; this.retrieveRawValue = retrieveRawValue; this.retrieveParameterStatus = retrieveParameterStatus; this.iterator = iterator; if(ascending) { goToFirstAscending(); } else { goToFirstDescending(); } } private void goToFirstDescending() { iterator.seek(new SegmentKey(parameterId, parameterGroupId, SortedTimeSegment.getSegmentStart(stop), Byte.MAX_VALUE).encode()); if(!iterator.isValid()) { iterator.seekToLast(); } else { currentKey = SegmentKey.decode(iterator.key()); if((currentKey.parameterGroupId != parameterGroupId) || (currentKey.parameterId!=parameterId) || currentKey.segmentStart>SortedTimeSegment.getSegmentStart(stop)) { iterator.prev(); } } if(!iterator.isValid()) { valid = false; } else { nextDescending(); } } private void goToFirstAscending() { iterator.seek(new SegmentKey(parameterId, parameterGroupId, SortedTimeSegment.getSegmentStart(start), (byte)0).encode()); if(!iterator.isValid()) { valid = false; } else { nextAscending(); } } public void next() { if(!iterator.isValid()) { valid = false; return; } if(ascending) { nextAscending(); } else { nextDescending(); } } void nextAscending() { currentKey = SegmentKey.decode(iterator.key()); if((currentKey.parameterGroupId != parameterGroupId) || (currentKey.parameterId != parameterId) || (currentKey.segmentStart>stop)) { valid = false; return; } valid = true; SegmentKey key = currentKey; while((key.segmentStart == currentKey.segmentStart) && (key.parameterGroupId==parameterGroupId) && (key.parameterId==parameterId)) { loadSegment(key.type); iterator.next(); if(iterator.isValid()) { key = SegmentKey.decode(iterator.key()); } else { break; } } } void nextDescending() { currentKey = SegmentKey.decode(iterator.key()); if((currentKey.parameterGroupId!=parameterGroupId) || (currentKey.parameterId!=parameterId) || (currentKey.segmentStart < SortedTimeSegment.getSegmentStart(start))) { valid = false; return; } valid = true; SegmentKey key = currentKey; while((key.segmentStart == currentKey.segmentStart) && (key.parameterGroupId==parameterGroupId) && (key.parameterId==parameterId)) { loadSegment(key.type); iterator.prev(); if(iterator.isValid()) { key = SegmentKey.decode(iterator.key()); } else { break; } } } private void loadSegment(byte type) { if((type==SegmentKey.TYPE_ENG_VALUE) && retrieveEngValue) { currentEngValueSegment = iterator.value(); } if((type==SegmentKey.TYPE_RAW_VALUE) && retrieveRawValue) { currentRawValueSegment = iterator.value(); } if((type==SegmentKey.TYPE_PARAMETER_STATUS) && retrieveParameterStatus) { currentStatusSegment = iterator.value(); } } SegmentKey key() { return currentKey; } BaseSegment engValue() { if(currentEngValueSegment ==null) { return null; } try { return (BaseSegment) segmentEncoder.decode(currentEngValueSegment, currentKey.segmentStart); } catch (DecodingException e) { throw new DatabaseCorruptionException(e); } } BaseSegment rawValue() { if(currentRawValueSegment ==null) { return null; } try { return (BaseSegment) segmentEncoder.decode(currentRawValueSegment, currentKey.segmentStart); } catch (DecodingException e) { throw new DatabaseCorruptionException(e); } } ParameterStatusSegment parameterStatus() { if(currentStatusSegment==null) { return null; } try { return (ParameterStatusSegment) segmentEncoder.decode(currentStatusSegment, currentKey.segmentStart); } catch (DecodingException e) { throw new DatabaseCorruptionException(e); } } boolean isValid() { return valid; } public int getParameterGroupId() { return parameterGroupId; } public int getParameterId() { return parameterId; } }