async Task <bool> IScreenBuffer.MoveToBookmark( IBookmark bookmark, BookmarkLookupMode mode, CancellationToken cancellation) { var matchMode = mode & BookmarkLookupMode.MatchModeMask; Func <DisplayLine, int> cmp = (DisplayLine l) => { var ret = MessagesComparer.CompareLogSourceConnectionIds(l.Message.GetConnectionId(), bookmark.LogSourceConnectionId); if (ret == 0) { ret = Math.Sign(l.Message.Position - bookmark.Position); } if (ret == 0) { ret = Math.Sign(l.LineIndex - bookmark.LineIndex); } return(ret); }; return(await PerformBuffersTransaction( string.Format("MoveToBookmark({0})", mode), cancellation, modifyBuffers : tmp => Task.WhenAll(tmp.Select(buf => matchMode == BookmarkLookupMode.ExactMatch && buf.Source.LogSourceHint?.ConnectionId == bookmark.LogSourceConnectionId ? buf.LoadAround(bookmark.Position, GetMaxBufferSize(viewSize) + bookmark.LineIndex, cancellation) : buf.LoadAt(bookmark.Time.ToLocalDateTime(), GetMaxBufferSize(viewSize) + bookmark.LineIndex, cancellation) )), getPivotLine : (lines, bufs) => { DisplayLine ret = new DisplayLine(); if (matchMode == BookmarkLookupMode.ExactMatch) { ret = lines.FirstOrDefault(l => cmp(l) == 0); } else if (matchMode == BookmarkLookupMode.FindNearestMessage) { ret = lines.FirstOrDefault(l => cmp(l) >= 0); if (ret.IsEmpty) { ret = lines.LastOrDefault(l => cmp(l) < 0); } } return ret.Message == null ? null : Tuple.Create(ret, ComputeMatchedLinePosition(mode)); } ) != null); }
double ComputeMatchedLinePosition(BookmarkLookupMode mode) { return((mode & BookmarkLookupMode.MoveBookmarkToMiddleOfScreen) != 0 ? Math.Max(viewSize - 1d, 0) / 2d : 0d); }
async Task <bool> IScreenBuffer.MoveToBookmark( IBookmark bookmark, BookmarkLookupMode mode, CancellationToken cancellation) { using (CreateTrackerForNewOperation(string.Format("MoveToBookmark({0})", mode), cancellation)) { var matchMode = mode & BookmarkLookupMode.MatchModeMask; MessageTimestamp dt = bookmark.Time; long position = bookmark.Position; int lineIndex = bookmark.LineIndex; string logSourceCollectionId = bookmark.LogSourceConnectionId; var tmp = buffers.ToDictionary(s => s.Key, s => new SourceBuffer(s.Value)); var tasks = tmp.Select(s => new { buf = s.Value, task = (buffers.Count == 1 && matchMode == BookmarkLookupMode.ExactMatch) ? GetScreenBufferLines(s.Key, position, bufferSize, EnumMessagesFlag.Forward | EnumMessagesFlag.IsActiveLogPositionHint, isRawLogMode, cancellation) : GetScreenBufferLines(s.Key, dt.ToLocalDateTime(), bufferSize, isRawLogMode, cancellation), }).ToList(); await Task.WhenAll(tasks.Select(i => i.task)); cancellation.ThrowIfCancellationRequested(); foreach (var t in tasks) { t.buf.Set(t.task.Result); } bool messageFound = false; if (matchMode == BookmarkLookupMode.FindNearestTime) { messageFound = true; } else { foreach (var i in GetMessagesInternal(tmp.Values).Forward(0, int.MaxValue)) { var cmp = MessagesComparer.CompareLogSourceConnectionIds(i.Message.Message.GetConnectionId(), logSourceCollectionId); if (cmp == 0) { cmp = Math.Sign(i.Message.Message.Position - position); } if (cmp == 0) { cmp = Math.Sign(((SourceBuffer)i.SourceCollection).Get(i.SourceIndex).LineIndex - lineIndex); } if (matchMode == BookmarkLookupMode.ExactMatch) { messageFound = cmp == 0; } else if (matchMode == BookmarkLookupMode.FindNearestBookmark) { messageFound = cmp > 0; } if (messageFound) { break; } var sb = ((SourceBuffer)i.SourceCollection); sb.UnnededTopMessages++; } } if (!messageFound) { if (matchMode == BookmarkLookupMode.FindNearestBookmark) { await MoveToStreamsEndInternal(cancellation); return(true); } return(false); } buffers = tmp; FinalizeSourceBuffers(); if (AllLogsAreAtEnd()) { await MoveToStreamsEndInternal(cancellation); } else { SetScrolledLines(0); if ((mode & BookmarkLookupMode.MoveBookmarkToMiddleOfScreen) != 0) { var additionalSpace = ((int)Math.Floor(viewSize) - 1) / 2; if (additionalSpace > 0) { await ShiftByInternal(-additionalSpace, cancellation); } } } return(true); } }