void IAsyncLogProviderCommandHandler.ContinueAsynchronously(CommandContext ctx) { result = new DateBoundPositionResponseData(); result.Position = PositionedMessagesUtils.LocateDateBound(ctx.Reader, date, bound, ctx.Cancellation); ctx.Tracer.Info("Position to return: {0}", result.Position); if (result.Position == ctx.Reader.EndPosition) { result.IsEndPosition = true; ctx.Tracer.Info("It is END position"); } else if (result.Position == ctx.Reader.BeginPosition - 1) { result.IsBeforeBeginPosition = true; ctx.Tracer.Info("It is BEGIN-1 position"); } else { ctx.Cancellation.ThrowIfCancellationRequested(); if (userNeedsDate) { result.Date = PositionedMessagesUtils.ReadNearestMessageTimestamp(ctx.Reader, result.Position); ctx.Tracer.Info("Date to return: {0}", result.Date); } } dateBoundsCache.Set(date, result); }
async Task IAsyncLogProviderCommandHandler.ContinueAsynchronously(CommandContext ctx) { result = new DateBoundPositionResponseData(); result.Position = await PositionedMessagesUtils.LocateDateBound(ctx.Reader, date, bound, ctx.Cancellation); ctx.Tracer.Info("Position to return: {0}", result.Position); if (result.Position == ctx.Reader.EndPosition) { result.IsEndPosition = true; ctx.Tracer.Info("It is END position"); } else if (result.Position == ctx.Reader.BeginPosition - 1) { result.IsBeforeBeginPosition = true; ctx.Tracer.Info("It is BEGIN-1 position"); } else { ctx.Cancellation.ThrowIfCancellationRequested(); if (messageRequested) { result.Message = await PositionedMessagesUtils.ReadNearestMessage(ctx.Reader, result.Position, MessagesParserFlag.HintMessageContentIsNotNeeed); ctx.Tracer.Info("Details to return: {0} at {1}", result.Message?.Time, result.Message?.Position); } } dateBoundsCache.Set(date, result); }
Task <DateBoundPositionResponseData> ITimeGapsSource.GetDateBoundPosition(DateTime d, ListUtils.ValueBound bound, CancellationToken cancellation) { var ret = new DateBoundPositionResponseData() { IsEndPosition = true, IsBeforeBeginPosition = true }; bool findSmallestDate = bound == ListUtils.ValueBound.Lower || bound == ListUtils.ValueBound.Upper; foreach (var r in EnumVisibleResults().Select(r => r.GetLastSnapshot()).Where(s => s != null)) { var bnd = r.GetDateBoundPosition(d, bound); if (bnd.Date != null) { if (ret.Date == null) { ret.Date = bnd.Date; } else if (findSmallestDate) { if (bnd.Date.Value < ret.Date.Value) { ret.Date = bnd.Date; } } else { if (bnd.Date.Value > ret.Date.Value) { ret.Date = bnd.Date; } } } if (!bnd.IsBeforeBeginPosition) { ret.IsBeforeBeginPosition = false; } if (!bnd.IsEndPosition) { ret.IsEndPosition = false; } ret.Position += bnd.Index; // use sum of indexes as virtual position } return(Task.FromResult(ret)); }
void IDateBoundsCache.Set(DateTime d, DateBoundPositionResponseData rsp) { lock (sync) { data[d] = new DateBoundsCache.Entry() { lastUsed = ++time, value = rsp }; int sizeThreshold = 512; if (data.Count > sizeThreshold) { // drop half of oldest entries when the threshold is reached data = data .OrderByDescending(x => x.Value.lastUsed) .Take(sizeThreshold / 2) .ToDictionary(x => x.Key, x => x.Value); } } }
bool IAsyncLogProviderCommandHandler.RunSynchronously(CommandContext ctx) { if (!userNeedsDate && (result = dateBoundsCache.Get(date)) != null) { return(true); } if (ctx.Cache == null || ctx.Cache.Messages.Count == 0) { return(false); } var cache = ctx.Cache; if ((date < ctx.Stats.AvailableTime.Begin && (bound == ListUtils.ValueBound.LowerReversed || bound == ListUtils.ValueBound.UpperReversed)) || date == ctx.Stats.AvailableTime.Begin && (bound == ListUtils.ValueBound.UpperReversed)) { result = new DateBoundPositionResponseData() { IsBeforeBeginPosition = true, Position = ctx.Stats.PositionsRange.Begin - 1 }; return(true); } if ((date >= ctx.Stats.AvailableTime.End && (bound == ListUtils.ValueBound.Lower || bound == ListUtils.ValueBound.Upper))) { result = new DateBoundPositionResponseData() { IsEndPosition = true, Position = ctx.Stats.PositionsRange.End }; return(true); } result = cache.Messages.GetDateBoundPosition(date, bound); if (result.Index == 0) { if (cache.MessagesRange.Begin != ctx.Stats.PositionsRange.Begin && (bound == ListUtils.ValueBound.Lower || bound == ListUtils.ValueBound.Upper)) { return(false); } } else if (result.Index == -1) { if (cache.MessagesRange.Begin != ctx.Stats.PositionsRange.Begin) { return(false); } } if (result.Index == cache.Messages.Count - 1) { if (cache.MessagesRange.End != ctx.Stats.PositionsRange.End && (bound == ListUtils.ValueBound.LowerReversed || bound == ListUtils.ValueBound.UpperReversed)) { return(false); } } else if (result.Index == cache.Messages.Count) { if (cache.MessagesRange.End != ctx.Stats.PositionsRange.End) { return(false); } } return(true); }
bool HandleResponse(DateBoundPositionResponseData res, bool reversedMode) { using (trace.NewFrame) { Predicate <MessageTimestamp> shouldAdvanceDate = d => reversedMode ? d > currentDate : d < currentDate; bool readerAdvanced = false; trace.Info("reader returned ({0}, {1})", res.Position, res.Message?.Time); trace.Info("reader's current position: {0}", currentPosition); bool advancePosition = true; if (reversedMode) { if (res.IsBeforeBeginPosition) { trace.Info("it's invalid position (before begin)"); advancePosition = false; } } else { if (res.IsEndPosition) { trace.Info("it's invalid position (end)"); advancePosition = false; } } if (advancePosition && res.Position > currentPosition) { trace.Info("reader has advanced its position: {0}", res.Position); readerAdvanced = true; currentPosition = res.Position; } bool advanceDate; if (res.Message == null) { advanceDate = false; } else { advanceDate = shouldAdvanceDate(res.Message.Time); } if (advanceDate) { trace.Info("reader might need to advance the current date from {0} to {1}. Getting writer lock to make final decision...", currentDate, res.Message.Time); if (shouldAdvanceDate(res.Message.Time)) { trace.Info("reader is really advancing the current date from {0} to {1}", currentDate, res.Message.Time); currentDate = res.Message.Time; } else { trace.Info("false alarm: reader is not advancing the current date because it has been already advanced to {0} by some other reader", currentDate); } } return(readerAdvanced); } }