private static int GetLogicalPosition(ReaderWorkItem workItem) { return workItem.IsMemory ? (int)workItem.Stream.Position : (int)workItem.Stream.Position - ChunkHeader.Size; }
private static bool TryReadBackwardInternal(ReaderWorkItem workItem, int actualPosition, out int length, out LogRecord record) { length = -1; record = null; if (actualPosition < 2 * sizeof(int)) // no space even for length prefix and suffix return false; var realPos = GetRealPosition(actualPosition, workItem.IsMemory); workItem.Stream.Position = realPos - sizeof(int); length = workItem.Reader.ReadInt32(); if (length <= 0) { throw new ArgumentException( string.Format("Log record that ends at actual pos {0} has non-positive length: {1}. " + "Something is seriously wrong.", actualPosition, length)); } if (length > TFConsts.MaxLogRecordSize) { throw new ArgumentException( string.Format("Log record that ends at actual pos {0} has too large length: {1} bytes, " + "while limit is {2} bytes.", actualPosition, length, TFConsts.MaxLogRecordSize)); } if (actualPosition < length + 2 * sizeof(int)) // no space for record + length prefix and suffix throw new UnableToReadPastEndOfStreamException(); workItem.Stream.Position = realPos - length - sizeof(int); record = LogRecord.ReadFrom(workItem.Reader); #if DEBUG workItem.Stream.Position = realPos - length - 2*sizeof(int); var prefixLength = workItem.Reader.ReadInt32(); Debug.Assert(prefixLength == length); #endif return true; }
private bool TryReadForwardInternal(ReaderWorkItem workItem, int actualPosition, out int length, out LogRecord record) { length = -1; record = null; workItem.Stream.Position = GetRealPosition(actualPosition, workItem.IsMemory); if (!VerifyDataLengthForward(workItem, 2*sizeof(int))) return false; length = workItem.Reader.ReadInt32(); if (length <= 0) { throw new ArgumentException( string.Format("Log record at actual pos {0} has non-positive length: {1}. " + "Something is seriously wrong.", actualPosition, length)); } if (length > TFConsts.MaxLogRecordSize) { throw new ArgumentException( string.Format("Log record at actual pos {0} has too large length: {1} bytes, " + "while limit is {2} bytes.", actualPosition, length, TFConsts.MaxLogRecordSize)); } if (!VerifyDataLengthForward(workItem, length + sizeof(int) /*suffix*/)) throw new UnableToReadPastEndOfStreamException(); record = LogRecord.ReadFrom(workItem.Reader); Debug.Assert(workItem.Reader.ReadInt32() == length); // verify suffix length == prefix length return true; }
private bool VerifyDataLengthForward(ReaderWorkItem workItem, int length) { var chunkSize = _isReadonly ? _chunkFooter.ActualDataSize : _chunkHeader.ChunkSize; return GetLogicalPosition(workItem) + length <= chunkSize; }
private int TranslateExactWithMidpoints(ReaderWorkItem workItem, Midpoint[] midpoints, int pos) { if (pos < midpoints[0].LogPos || pos > midpoints[midpoints.Length - 1].LogPos) return -1; var recordRange = LocatePosRange(midpoints, pos); return TranslateExactWithoutMidpoints(workItem, pos, recordRange.Item1, recordRange.Item2); }
private int TranslateExactWithoutMidpoints(ReaderWorkItem workItem, int pos, int startIndex, int endIndex) { int low = startIndex; int high = endIndex; while (low <= high) { var mid = low + (high - low) / 2; var v = ReadPosMap(workItem, mid); if (v.LogPos == pos) return v.ActualPos; if (v.LogPos < pos) low = mid + 1; else high = mid - 1; } return -1; }
private Tuple<int, int> TranslateClosestForwardWithoutMidpoints(ReaderWorkItem workItem, int pos, int startIndex, int endIndex) { PosMap res = ReadPosMap(workItem, endIndex); if (pos > res.LogPos) return Tuple.Create(_actualDataSize, endIndex + 1); // to allow backward reading of the last record, forward read will decline anyway int low = startIndex; int high = endIndex; while (low < high) { var mid = low + (high - low) / 2; var v = ReadPosMap(workItem, mid); if (v.LogPos < pos) low = mid + 1; else { high = mid; res = v; } } return Tuple.Create(res.ActualPos, high); }
private bool TryReadRecordInternal(ReaderWorkItem workItem, int actualPosition, out int length, out LogRecord record) { length = -1; record = null; workItem.Stream.Position = GetRealPosition(actualPosition, workItem.IsMemory); if (!VerifyStreamLength(workItem.Stream, 4)) return false; length = workItem.Reader.ReadInt32(); CheckLength(workItem, length, actualPosition); record = LogRecord.ReadFrom(workItem.Reader); return true; }
private Tuple<int, int> TranslateClosestForwardPosition(ReaderWorkItem workItem, int logicalPosition) { if (!_isReadonly || _chunkFooter.MapSize == 0) { // this is mostly for ability to read closest backward from the very end var logicalPos = Math.Min(_actualDataSize, logicalPosition); return Tuple.Create(logicalPos, -1); } var midpoints = _midpoints; if (workItem.IsMemory || midpoints == null) { var mapCount = _chunkFooter.MapSize / sizeof(ulong); return TranslateClosestForwardWithoutMidpoints(workItem, logicalPosition, 0, mapCount - 1); } return TranslateClosestForwardWithMidpoints(workItem, midpoints, logicalPosition); }
private Tuple<int, int> TranslateClosestForwardWithMidpoints(ReaderWorkItem workItem, Midpoint[] midpoints, int pos) { if (pos > midpoints[midpoints.Length - 1].LogPos) return Tuple.Create(_actualDataSize, midpoints.Length); // to allow backward reading of the last record, forward read will decline anyway var recordRange = LocatePosRange(midpoints, pos); return TranslateClosestForwardWithoutMidpoints(workItem, pos, recordRange.Item1, recordRange.Item2); }
private int GetLogicalPosition(ReaderWorkItem workItem) { return(workItem.IsMemory ? (int)workItem.Stream.Position : (int)workItem.Stream.Position - ChunkHeader.Size); }
// private int TranslateClosestWithMidpoints(ReaderWorkItem workItem, Midpoint[] midpoints, int prevPos) // { // if (prevPos < midpoints[0].LogPos || prevPos >= midpoints[midpoints.Length - 1].LogPos) // return -1; // // var recordRange = LocateClosestPosRange(midpoints, prevPos); // return TranslateClosestWithoutMidpoints(workItem, prevPos, recordRange.Item1, recordRange.Item2); // } private Tuple<PosMap, int> TranslateSameOrClosestWithoutMidpoints(ReaderWorkItem workItem, int pos, int startIndex, int endIndex) { PosMap res = ReadPosMap(workItem, endIndex); if (pos > res.LogPos) return Tuple.Create(new PosMap(-1, -1), -1); int low = startIndex; int high = endIndex; while (low < high) { var mid = low + (high - low) / 2; var v = ReadPosMap(workItem, mid); if (v.LogPos < pos) low = mid + 1; else { high = mid; res = v; } } return Tuple.Create(res, high); }
private void CheckLength(ReaderWorkItem workItem, int length, int actualPosition) { if (length <= 0) { throw new ArgumentException( string.Format("Log record at actual pos {0} has non-positive length: {1}. " + "Something is seriously wrong.", actualPosition, length)); } if (length > TFConsts.MaxLogRecordSize) { throw new ArgumentException( string.Format("Log record at actual pos {0} has too large length: {1} bytes, " + "while limit is {2} bytes.", actualPosition, length, TFConsts.MaxLogRecordSize)); } if (!VerifyStreamLength(workItem.Stream, length)) throw new UnableToReadPastEndOfStreamException(); }
private PosMap ReadPosMap(ReaderWorkItem workItem, int index) { var pos = (workItem.IsMemory ? 0 : ChunkHeader.Size) + _chunkFooter.ActualChunkSize + (index << 3); workItem.Stream.Seek(pos, SeekOrigin.Begin); return new PosMap(workItem.Reader.ReadUInt64()); }
private int TranslateExactPosition(ReaderWorkItem workItem, int pos) { if (!_isReadonly || _chunkFooter.MapSize == 0) return pos; var midpoints = _midpoints; if (workItem.IsMemory || midpoints == null) { var mapCount = _chunkFooter.MapSize / sizeof(ulong); return TranslateExactWithoutMidpoints(workItem, pos, 0, mapCount - 1); } return TranslateExactWithMidpoints(workItem, midpoints, pos); }
private void ReturnReaderWorkItem(ReaderWorkItem item) { if (item.IsMemory) { _memoryStreams.Enqueue(item); if (!_cached || _selfdestructin54321) TryDestructUnmanagedMemory(); } else { _streams.Enqueue(item); if (_selfdestructin54321) TryDestruct(); } }
private Tuple<PosMap, int> TranslateToSameOrClosestPosition(ReaderWorkItem workItem, int logicalPosition) { if (!_isReadonly || _chunkFooter.MapSize == 0) { return Tuple.Create(new PosMap(logicalPosition, logicalPosition), -1); } else { return TranslateSameOrClosestWithoutMidpoints(workItem, logicalPosition, 0, _chunkFooter.MapSize/sizeof(ulong) - 1); } }