private ReadResult Read() { if (_loadMore) { if (_remaining != 0) { var take = (int)Math.Min(_remaining, _pageSize); DebugLog($"Loading {take} bytes from offet {_offset}..."); var accessor = _file.CreateViewAccessor(_offset, take, MemoryMappedFileAccess.Read); var next = new MappedPage(accessor, _offset, take); Debug.Assert(next.RunningIndex == _offset); _remaining -= take; _offset += take; if (_first == null) { _first = _last = next; } else { _last.Next = next; _last = next; } DebugLog($"Loaded page {next}"); } _loadMore = false; } if (_first == null) { Debug.Assert(_remaining == 0, "unexpected EOF"); DebugLog($"Read has encountered EOF"); return(new ReadResult(default, false, true));
private static long CountAvailable(MappedPage page) { long total = 0; while (page != null) { total += page.Capacity - page.Consumed; page = page.Next; } return(total); }
/// <summary> /// Releases all resources associated with the object /// </summary> public void Dispose() { var page = _first; while (page != null) { try { page.Dispose(); } catch { } page = page.Next; } _first = _last = null; try { _file?.Dispose(); } catch { } _file = null; }
/// <summary> /// Indicates how much data was consumed, and how much examined, from a read operation /// </summary> public override void AdvanceTo(SequencePosition consumed, SequencePosition examined) { var cPage = (MappedPage)consumed.GetObject(); var ePage = (MappedPage)examined.GetObject(); if (cPage == null || ePage == null) { if (_first == null) { return; // that's fine - means they called Advance on an empty EOF } Throw.Argument("Invalid position; consumed/examined must remain inside the buffer"); } Debug.Assert(ePage != null, "No examined page"); Debug.Assert(cPage != null, "No consumed page"); MappedPage newKeep; var cOffset = consumed.GetInteger(); if (cOffset == cPage.Capacity) { newKeep = cPage.Next; } else { newKeep = cPage; newKeep.Consumed = cOffset; } if (newKeep == null) { DebugLog($"Retaining nothing"); _last = null; } else { DebugLog($"Retaining page {newKeep}"); } // now drop any pages we don't need if (newKeep != _first) { var page = _first; while (page != null && page != newKeep) { DebugLog($"Dropping page {page}"); page.Dispose(); page = page.Next; } _first = newKeep; } // check whether they looked at everything if (_last == null) { _loadMore = true; // definitely } else { var eOffset = examined.GetInteger(); _loadMore = ePage == _last && eOffset == ePage.Capacity; } DebugLog($"After AdvanceTo, {CountAvailable(_first)} available bytes, {_remaining} remaining unloaded bytes, load more: {_loadMore}"); }