/// <summary> /// Pull-based iterator interface for scanning FASTER log /// </summary> /// <param name="beginAddress">Begin address for scan.</param> /// <param name="endAddress">End address for scan (or long.MaxValue for tailing).</param> /// <param name="name">Name of iterator, if we need to persist/recover it (default null - do not persist).</param> /// <param name="recover">Whether to recover named iterator from latest commit (if exists). If false, iterator starts from beginAddress.</param> /// <param name="scanBufferingMode">Use single or double buffering</param> /// <param name="scanUncommitted">Whether we scan uncommitted data</param> /// <returns></returns> public FasterLogScanIterator Scan(long beginAddress, long endAddress, string name = null, bool recover = true, ScanBufferingMode scanBufferingMode = ScanBufferingMode.DoublePageBuffering, bool scanUncommitted = false) { FasterLogScanIterator iter; if (recover && name != null && RecoveredIterators != null && RecoveredIterators.ContainsKey(name)) { iter = new FasterLogScanIterator(this, allocator, RecoveredIterators[name], endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted); } else { iter = new FasterLogScanIterator(this, allocator, beginAddress, endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted); } if (name != null) { if (name.Length > 20) { throw new FasterException("Max length of iterator name is 20 characters"); } if (PersistedIterators.ContainsKey(name)) { Debug.WriteLine("Iterator name exists, overwriting"); } PersistedIterators[name] = iter; } if (Interlocked.Increment(ref logRefCount) == 1) { throw new FasterException("Cannot scan disposed log instance"); } return(iter); }
/// <summary> /// Pull-based iterator interface for scanning FASTER log /// </summary> /// <param name="beginAddress">Begin address for scan.</param> /// <param name="endAddress">End address for scan (or long.MaxValue for tailing).</param> /// <param name="name">Name of iterator, if we need to persist/recover it (default null - do not persist).</param> /// <param name="recover">Whether to recover named iterator from latest commit (if exists). If false, iterator starts from beginAddress.</param> /// <param name="scanBufferingMode">Use single or double buffering</param> /// <returns></returns> public FasterLogScanIterator Scan(long beginAddress, long endAddress, string name = null, bool recover = true, ScanBufferingMode scanBufferingMode = ScanBufferingMode.DoublePageBuffering) { FasterLogScanIterator iter; if (recover && name != null && RecoveredIterators != null && RecoveredIterators.ContainsKey(name)) { iter = new FasterLogScanIterator(this, allocator, RecoveredIterators[name], endAddress, getMemory, scanBufferingMode, epoch, headerSize, name); } else { iter = new FasterLogScanIterator(this, allocator, beginAddress, endAddress, getMemory, scanBufferingMode, epoch, headerSize, name); } if (name != null) { if (name.Length > 20) { throw new Exception("Max length of iterator name is 20 characters"); } if (FasterLogScanIterator.PersistedIterators.ContainsKey(name)) { Debug.WriteLine("Iterator name exists, overwriting"); } FasterLogScanIterator.PersistedIterators[name] = iter; } return(iter); }
private static async ValueTask <bool> SlowWaitUncommittedAsync(FasterLogScanIterator @this, CancellationToken token) { while (true) { if (@this.disposed) { return(false); } var refreshUncommittedTask = @this.fasterLog.RefreshUncommittedTask; if (@this.NextAddress < @this.fasterLog.SafeTailAddress) { return(true); } // Ignore refresh-uncommitted exceptions, except when the token is signaled try { await refreshUncommittedTask.WithCancellationAsync(token); } catch (ObjectDisposedException) { return(false); } catch when(!token.IsCancellationRequested) { } } }
private static async ValueTask <bool> SlowWaitAsync(FasterLogScanIterator @this, CancellationToken token) { while (true) { if (@this.disposed) { return(false); } if (@this.Ended) { return(false); } var commitTask = @this.fasterLog.CommitTask; if (@this.NextAddress < @this.fasterLog.CommittedUntilAddress) { return(true); } // Ignore commit exceptions, except when the token is signaled try { await commitTask.WithCancellationAsync(token).ConfigureAwait(false); } catch (ObjectDisposedException) { return(false); } catch when(!token.IsCancellationRequested) { } } }
// use static local function to guarantee there's no accidental closure getting allocated here static async ValueTask SlowWaitAsync(FasterLogScanIterator @this, CancellationToken token) { while (true) { var commitTask = @this.fasterLog.CommitTask; if (@this.nextAddress >= @this.fasterLog.CommittedUntilAddress) { // Ignore commit exceptions, except when the token is signaled try { await commitTask.WithCancellationAsync(token); } catch when(!token.IsCancellationRequested) { } } else { break; } } }