internal DeleteAsyncResult(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, ExceptionDispatchInfo exceptionDispatchInfo) { this.Status = new(StatusCode.Pending); updateAsyncInternal = new UpdateAsyncInternal <Input, Output, Context, DeleteAsyncOperation <Input, Output, Context>, DeleteAsyncResult <Input, Output, Context> >( fasterKV, fasterSession, currentCtx, pendingContext, exceptionDispatchInfo, new DeleteAsyncOperation <Input, Output, Context>()); }
/// <summary> /// Complete outstanding pending operations that were issued synchronously /// Async operations (e.g., ReadAsync) need to be completed individually /// </summary> /// <returns></returns> internal async ValueTask CompletePendingAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, CancellationToken token, CompletedOutputIterator <Key, Value, Input, Output, Context> completedOutputs) { while (true) { fasterSession.UnsafeResumeThread(); try { InternalCompletePendingRequests(currentCtx, currentCtx, fasterSession, completedOutputs); InternalCompleteRetryRequests(currentCtx, currentCtx, fasterSession); } finally { fasterSession.UnsafeSuspendThread(); } await currentCtx.WaitPendingAsync(token).ConfigureAwait(false); if (currentCtx.HasNoPendingRequests) { return; } InternalRefresh(currentCtx, fasterSession); Thread.Yield(); } }
private static async ValueTask <ReadAsyncResult <Input, Output, Context> > SlowReadAsync <Input, Output, Context>( FasterKV <Key, Value> @this, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, CancellationToken token = default) { currentCtx.asyncPendingCount++; currentCtx.pendingReads.Add(); ExceptionDispatchInfo exceptionDispatchInfo = default; try { token.ThrowIfCancellationRequested(); if (@this.epoch.ThisInstanceProtected()) { throw new NotSupportedException("Async operations not supported over protected epoch"); } using (token.Register(() => diskRequest.asyncOperation.TrySetCanceled())) diskRequest = await diskRequest.asyncOperation.Task.WithCancellationAsync(token).ConfigureAwait(false); } catch (Exception e) { exceptionDispatchInfo = ExceptionDispatchInfo.Capture(e); } return(new ReadAsyncResult <Input, Output, Context>(@this, fasterSession, currentCtx, pendingContext, diskRequest, exceptionDispatchInfo)); }
internal DeleteAsyncResult(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, Task flushTask, ExceptionDispatchInfo exceptionDispatchInfo) { internalStatus = OperationStatus.ALLOCATE_FAILED; updelAsyncInternal = new UpdelAsyncInternal <Input, Output, Context, DeleteAsyncOperation <Input, Output, Context>, DeleteAsyncResult <Input, Output, Context> >( fasterKV, fasterSession, currentCtx, pendingContext, flushTask, exceptionDispatchInfo); }
internal UpsertAsyncResult(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, TOutput, Context> fasterSession, FasterExecutionContext <Input, TOutput, Context> currentCtx, PendingContext <Input, TOutput, Context> pendingContext, ExceptionDispatchInfo exceptionDispatchInfo) { this.Status = new(StatusCode.Pending); this.Output = default; this.RecordMetadata = default; updateAsyncInternal = new UpdateAsyncInternal <Input, TOutput, Context, UpsertAsyncOperation <Input, TOutput, Context>, UpsertAsyncResult <Input, TOutput, Context> >( fasterKV, fasterSession, currentCtx, pendingContext, exceptionDispatchInfo, new UpsertAsyncOperation <Input, TOutput, Context>()); }
internal RmwAsyncResult(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, ExceptionDispatchInfo exceptionDispatchInfo) { Status = Status.PENDING; output = default; updateAsyncInternal = new UpdateAsyncInternal <Input, Output, Context, RmwAsyncOperation <Input, Output, Context>, RmwAsyncResult <Input, Output, Context> >( fasterKV, fasterSession, currentCtx, pendingContext, exceptionDispatchInfo, new RmwAsyncOperation <Input, Output, Context>(diskRequest)); }
private static async ValueTask <DeleteAsyncResult <Input, Output, Context> > SlowDeleteAsync <Input, Output, Context>( FasterKV <Key, Value> @this, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pcontext, CompletionEvent flushEvent, CancellationToken token = default) { ExceptionDispatchInfo exceptionDispatchInfo = await WaitForFlushCompletionAsync(@this, currentCtx, flushEvent, token).ConfigureAwait(false); return(new DeleteAsyncResult <Input, Output, Context>(@this, fasterSession, currentCtx, pcontext, exceptionDispatchInfo)); }
private static ValueTask <DeleteAsyncResult <Input, Output, Context> > SlowDeleteAsync <Input, Output, Context>( FasterKV <Key, Value> @this, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, Task flushTask, CancellationToken token = default) { ExceptionDispatchInfo exceptionDispatchInfo = GetSlowUpdelAsyncExceptionDispatchInfo(@this, currentCtx, token); return(new ValueTask <DeleteAsyncResult <Input, Output, Context> >(new DeleteAsyncResult <Input, Output, Context>(@this, fasterSession, currentCtx, pendingContext, flushTask, exceptionDispatchInfo))); }
/// <summary> /// Complete outstanding pending operations that were issued synchronously /// Async operations (e.g., ReadAsync) need to be completed individually /// </summary> /// <returns></returns> internal async ValueTask CompletePendingAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, CancellationToken token, CompletedOutputIterator <Key, Value, Input, Output, Context> completedOutputs) { while (true) { bool done = true; #region Previous pending requests if (!RelaxedCPR) { if (currentCtx.phase == Phase.IN_PROGRESS || currentCtx.phase == Phase.WAIT_PENDING) { fasterSession.UnsafeResumeThread(); try { InternalCompletePendingRequests(currentCtx.prevCtx, currentCtx, fasterSession, completedOutputs); InternalCompleteRetryRequests(currentCtx.prevCtx, currentCtx, fasterSession); } finally { fasterSession.UnsafeSuspendThread(); } await currentCtx.prevCtx.WaitPendingAsync(token).ConfigureAwait(false); done &= currentCtx.prevCtx.HasNoPendingRequests; } } #endregion fasterSession.UnsafeResumeThread(); try { InternalCompletePendingRequests(currentCtx, currentCtx, fasterSession, completedOutputs); InternalCompleteRetryRequests(currentCtx, currentCtx, fasterSession); } finally { fasterSession.UnsafeSuspendThread(); } await currentCtx.WaitPendingAsync(token).ConfigureAwait(false); done &= currentCtx.HasNoPendingRequests; if (done) { return; } InternalRefresh(currentCtx, fasterSession); Thread.Yield(); } }
internal ReadAsyncResult( FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, ExceptionDispatchInfo exceptionDispatchInfo) { status = Status.PENDING; output = default; this.recordInfo = default; readAsyncInternal = new ReadAsyncInternal <Input, Output, Context>(fasterKV, fasterSession, currentCtx, pendingContext, diskRequest, exceptionDispatchInfo); }
internal ReadAsyncInternal(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, ExceptionDispatchInfo exceptionDispatchInfo) { _exception = exceptionDispatchInfo; _fasterKV = fasterKV; _fasterSession = fasterSession; _currentCtx = currentCtx; _pendingContext = pendingContext; _diskRequest = diskRequest; CompletionComputeStatus = Pending; _recordInfo = default; }
internal UpdateAsyncInternal(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, ExceptionDispatchInfo exceptionDispatchInfo, TAsyncOperation asyncOperation) { _exception = exceptionDispatchInfo; _fasterKV = fasterKV; _fasterSession = fasterSession; _currentCtx = currentCtx; _pendingContext = pendingContext; _asyncOperation = asyncOperation; CompletionComputeStatus = Pending; }
internal UpdelAsyncInternal(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, Task flushTask, ExceptionDispatchInfo exceptionDispatchInfo) { _exception = exceptionDispatchInfo; _fasterKV = fasterKV; _fasterSession = fasterSession; _currentCtx = currentCtx; _pendingContext = pendingContext; _flushTask = flushTask; asyncOperation = new TAsyncOperation(); CompletionComputeStatus = Pending; }
/// <inheritdoc/> public bool CompletePendingIO(IFasterSession <Key, Value, Input, Output, Context> fasterSession) { if (this.diskRequest.IsDefault()) { return(false); } // CompletePending() may encounter OperationStatus.ALLOCATE_FAILED; if so, we don't have a more current flushEvent to pass back. fasterSession.CompletePendingWithOutputs(out var completedOutputs, wait: true, spinWaitForCommit: false); var status = completedOutputs.Next() ? completedOutputs.Current.Status : Status.ERROR; completedOutputs.Dispose(); return(status != Status.PENDING); }
/// <summary> /// Complete outstanding pending operations that were issued synchronously /// Async operations (e.g., ReadAsync) need to be completed individually /// </summary> /// <returns></returns> internal async ValueTask CompletePendingAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, CancellationToken token = default) { bool done = true; #region Previous pending requests if (!RelaxedCPR) { if (currentCtx.phase == Phase.IN_PROGRESS || currentCtx.phase == Phase.WAIT_PENDING) { await currentCtx.prevCtx.pendingReads.WaitUntilEmptyAsync(token); await InternalCompletePendingRequestsAsync(currentCtx.prevCtx, currentCtx, fasterSession, token); Debug.Assert(currentCtx.prevCtx.SyncIoPendingCount == 0); if (currentCtx.prevCtx.retryRequests.Count > 0) { fasterSession.UnsafeResumeThread(); InternalCompleteRetryRequests(currentCtx.prevCtx, currentCtx, fasterSession); fasterSession.UnsafeSuspendThread(); } done &= (currentCtx.prevCtx.HasNoPendingRequests); } } #endregion await InternalCompletePendingRequestsAsync(currentCtx, currentCtx, fasterSession, token); fasterSession.UnsafeResumeThread(); InternalCompleteRetryRequests(currentCtx, currentCtx, fasterSession); fasterSession.UnsafeSuspendThread(); Debug.Assert(currentCtx.HasNoPendingRequests); done &= (currentCtx.HasNoPendingRequests); if (!done) { throw new Exception("CompletePendingAsync did not complete"); } }
internal ValueTask <DeleteAsyncResult <Input, Output, Context> > DeleteAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref PendingContext <Input, Output, Context> pcontext, ref Key key, Context userContext, long serialNo, CancellationToken token) { CompletionEvent flushEvent; fasterSession.UnsafeResumeThread(); try { OperationStatus internalStatus; do { flushEvent = hlog.FlushEvent; internalStatus = InternalDelete(ref key, ref userContext, ref pcontext, fasterSession, currentCtx, serialNo); } while (internalStatus == OperationStatus.RETRY_NOW); if (OperationStatusUtils.TryConvertToStatusCode(internalStatus, out Status status)) { return(new ValueTask <DeleteAsyncResult <Input, Output, Context> >(new DeleteAsyncResult <Input, Output, Context>(new(internalStatus)))); } Debug.Assert(internalStatus == OperationStatus.ALLOCATE_FAILED); } finally { Debug.Assert(serialNo >= currentCtx.serialNum, "Operation serial numbers must be non-decreasing"); currentCtx.serialNum = serialNo; fasterSession.UnsafeSuspendThread(); } return(SlowDeleteAsync(this, fasterSession, currentCtx, pcontext, flushEvent, token)); }
internal ValueTask <DeleteAsyncResult <Input, Output, Context> > DeleteAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref Key key, Context userContext, long serialNo, CancellationToken token = default) { var pcontext = new PendingContext <Input, Output, Context> { IsAsync = true }; return(DeleteAsync(fasterSession, currentCtx, ref pcontext, ref key, userContext, serialNo, token)); }
private ValueTask <UpsertAsyncResult <Input, Output, Context> > UpsertAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref PendingContext <Input, Output, Context> pcontext, ref Key key, ref Input input, ref Value value, Context userContext, long serialNo, CancellationToken token) { CompletionEvent flushEvent; Output output = default; fasterSession.UnsafeResumeThread(); try { OperationStatus internalStatus; do { flushEvent = hlog.FlushEvent; internalStatus = InternalUpsert(ref key, ref input, ref value, ref output, ref userContext, ref pcontext, fasterSession, currentCtx, serialNo); } while (internalStatus == OperationStatus.RETRY_NOW); if (OperationStatusUtils.TryConvertToStatusCode(internalStatus, out Status status)) { return(new ValueTask <UpsertAsyncResult <Input, Output, Context> >(new UpsertAsyncResult <Input, Output, Context>(status, output, new RecordMetadata(pcontext.recordInfo, pcontext.logicalAddress)))); } Debug.Assert(internalStatus == OperationStatus.ALLOCATE_FAILED); } finally { Debug.Assert(serialNo >= currentCtx.serialNum, "Operation serial numbers must be non-decreasing"); currentCtx.serialNum = serialNo; fasterSession.UnsafeSuspendThread(); } return(SlowUpsertAsync(this, fasterSession, currentCtx, pcontext, flushEvent, token)); }
public OperationStatus DoFastOperation(FasterKV <Key, Value> fasterKV, PendingContext <Input, Output, Context> pendingContext, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx) => fasterKV.InternalDelete(ref pendingContext.key.Get(), ref pendingContext.userContext, ref pendingContext, fasterSession, currentCtx, pendingContext.serialNum);
/// <inheritdoc/> public Status DoFastOperation(FasterKV <Key, Value> fasterKV, ref PendingContext <Input, Output, Context> pendingContext, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, bool asyncOp, out CompletionEvent flushEvent, out Output output) { OperationStatus internalStatus; do { flushEvent = fasterKV.hlog.FlushEvent; internalStatus = fasterKV.InternalDelete(ref pendingContext.key.Get(), ref pendingContext.userContext, ref pendingContext, fasterSession, currentCtx, pendingContext.serialNum); } while (internalStatus == OperationStatus.RETRY_NOW); output = default; return(TranslateStatus(internalStatus)); }
internal ValueTask <RmwAsyncResult <Input, Output, Context> > RmwAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref Key key, ref Input input, Context context, long serialNo, CancellationToken token = default) { var pcontext = default(PendingContext <Input, Output, Context>); var diskRequest = default(AsyncIOContext <Key, Value>); fasterSession.UnsafeResumeThread(); try { OperationStatus internalStatus; do { internalStatus = InternalRMW(ref key, ref input, ref context, ref pcontext, fasterSession, currentCtx, serialNo); }while (internalStatus == OperationStatus.RETRY_NOW || internalStatus == OperationStatus.RETRY_LATER); if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND) { return(new ValueTask <RmwAsyncResult <Input, Output, Context> >(new RmwAsyncResult <Input, Output, Context>((Status)internalStatus, default)));
private ValueTask <UpsertAsyncResult <Input, Output, Context> > UpsertAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref PendingContext <Input, Output, Context> pcontext, ref Key key, ref Value value, Context userContext, long serialNo, CancellationToken token) { CompletionEvent flushEvent; fasterSession.UnsafeResumeThread(); try { OperationStatus internalStatus; do { flushEvent = hlog.FlushEvent; internalStatus = InternalUpsert(ref key, ref value, ref userContext, ref pcontext, fasterSession, currentCtx, serialNo); } while (internalStatus == OperationStatus.RETRY_NOW); if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND) { return(new ValueTask <UpsertAsyncResult <Input, Output, Context> >(new UpsertAsyncResult <Input, Output, Context>((Status)internalStatus))); } Debug.Assert(internalStatus == OperationStatus.ALLOCATE_FAILED); } finally { Debug.Assert(serialNo >= currentCtx.serialNum, "Operation serial numbers must be non-decreasing"); currentCtx.serialNum = serialNo; fasterSession.UnsafeSuspendThread(); } return(SlowUpsertAsync(this, fasterSession, currentCtx, pcontext, flushEvent, token)); }
/// <inheritdoc/> public Status DoFastOperation(FasterKV <Key, Value> fasterKV, ref PendingContext <Input, Output, Context> pendingContext, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, bool asyncOp, out CompletionEvent flushEvent, out Output output) { output = default; flushEvent = fasterKV.hlog.FlushEvent; Status status = !this.diskRequest.IsDefault() ? fasterKV.InternalCompletePendingRequestFromContext(currentCtx, currentCtx, fasterSession, this.diskRequest, ref pendingContext, asyncOp, out AsyncIOContext <Key, Value> newDiskRequest) : fasterKV.CallInternalRMW(fasterSession, currentCtx, ref pendingContext, ref pendingContext.key.Get(), ref pendingContext.input.Get(), pendingContext.userContext, pendingContext.serialNum, asyncOp, out flushEvent, out newDiskRequest); if (status == Status.PENDING && !newDiskRequest.IsDefault()) { flushEvent = default; this.diskRequest = newDiskRequest; } return(status); }
internal ValueTask <DeleteAsyncResult <Input, Output, Context> > DeleteAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref Key key, Context userContext, long serialNo, CancellationToken token = default) { var pcontext = default(PendingContext <Input, Output, Context>); pcontext.IsAsync = true; Task flushTask; fasterSession.UnsafeResumeThread(); try { OperationStatus internalStatus; do { flushTask = hlog.FlushTask; internalStatus = InternalDelete(ref key, ref userContext, ref pcontext, fasterSession, currentCtx, serialNo); } while (internalStatus == OperationStatus.RETRY_NOW); if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND) { return(new ValueTask <DeleteAsyncResult <Input, Output, Context> >(new DeleteAsyncResult <Input, Output, Context>(internalStatus))); } Debug.Assert(internalStatus == OperationStatus.ALLOCATE_FAILED); } finally { Debug.Assert(serialNo >= currentCtx.serialNum, "Operation serial numbers must be non-decreasing"); currentCtx.serialNum = serialNo; fasterSession.UnsafeSuspendThread(); } return(SlowDeleteAsync(this, fasterSession, currentCtx, pcontext, flushTask, token)); }
internal ValueTask <ReadAsyncResult <Input, Output, Context> > ReadAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref Key key, ref Input input, long startAddress, Context context, long serialNo, CancellationToken token, byte operationFlags = 0) { var pcontext = default(PendingContext <Input, Output, Context>); pcontext.SetOperationFlags(operationFlags, startAddress); var diskRequest = default(AsyncIOContext <Key, Value>); Output output = default; fasterSession.UnsafeResumeThread(); try { OperationStatus internalStatus = InternalRead(ref key, ref input, ref output, startAddress, ref context, ref pcontext, fasterSession, currentCtx, serialNo); Debug.Assert(internalStatus != OperationStatus.RETRY_NOW); Debug.Assert(internalStatus != OperationStatus.RETRY_LATER); if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND) { return(new ValueTask <ReadAsyncResult <Input, Output, Context> >(new ReadAsyncResult <Input, Output, Context>((Status)internalStatus, output, pcontext.recordInfo))); } else { var status = HandleOperationStatus(currentCtx, currentCtx, ref pcontext, fasterSession, internalStatus, true, out diskRequest); if (status != Status.PENDING) { return(new ValueTask <ReadAsyncResult <Input, Output, Context> >(new ReadAsyncResult <Input, Output, Context>(status, output, pcontext.recordInfo))); } } } finally { Debug.Assert(serialNo >= currentCtx.serialNum, "Operation serial numbers must be non-decreasing"); currentCtx.serialNum = serialNo; fasterSession.UnsafeSuspendThread(); } return(SlowReadAsync(this, fasterSession, currentCtx, pcontext, diskRequest, token)); }
/// <inheritdoc/> public ValueTask <DeleteAsyncResult <Input, Output, Context> > DoSlowOperation(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, CompletionEvent flushEvent, CancellationToken token) => SlowDeleteAsync(fasterKV, fasterSession, currentCtx, pendingContext, flushEvent, token);
/// <inheritdoc/> public bool CompletePendingIO(IFasterSession <Key, Value, Input, Output, Context> fasterSession) => false;
internal ValueTask <ReadAsyncResult <Input, Output, Context> > ReadAsync <Input, Output, Context>(IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, ref Key key, ref Input input, ref ReadOptions readOptions, Context context, long serialNo, CancellationToken token, bool noKey = false) { var pcontext = default(PendingContext <Input, Output, Context>); var operationFlags = PendingContext <Input, Output, Context> .GetOperationFlags(MergeReadFlags(currentCtx.ReadFlags, readOptions.ReadFlags), noKey); pcontext.SetOperationFlags(operationFlags, readOptions.StopAddress); var diskRequest = default(AsyncIOContext <Key, Value>); Output output = default; fasterSession.UnsafeResumeThread(); try { OperationStatus internalStatus; do { internalStatus = InternalRead(ref key, ref input, ref output, readOptions.StartAddress, ref context, ref pcontext, fasterSession, currentCtx, serialNo); }while (internalStatus == OperationStatus.RETRY_NOW); Debug.Assert(internalStatus != OperationStatus.RETRY_LATER); if (OperationStatusUtils.TryConvertToStatusCode(internalStatus, out Status status)) { return(new ValueTask <ReadAsyncResult <Input, Output, Context> >(new ReadAsyncResult <Input, Output, Context>(new(internalStatus), output, new RecordMetadata(pcontext.recordInfo, pcontext.logicalAddress)))); } status = HandleOperationStatus(currentCtx, currentCtx, ref pcontext, fasterSession, internalStatus, true, out diskRequest); if (!status.IsPending) { return(new ValueTask <ReadAsyncResult <Input, Output, Context> >(new ReadAsyncResult <Input, Output, Context>(status, output, new RecordMetadata(pcontext.recordInfo, pcontext.logicalAddress)))); } } finally { Debug.Assert(serialNo >= currentCtx.serialNum, "Operation serial numbers must be non-decreasing"); currentCtx.serialNum = serialNo; fasterSession.UnsafeSuspendThread(); } return(SlowReadAsync(this, fasterSession, currentCtx, pcontext, diskRequest, token)); }
public ValueTask <UpsertAsyncResult <Input, Output, Context> > DoSlowOperation(FasterKV <Key, Value> fasterKV, IFasterSession <Key, Value, Input, Output, Context> fasterSession, FasterExecutionContext <Input, Output, Context> currentCtx, PendingContext <Input, Output, Context> pendingContext, Task flushTask, CancellationToken token) => SlowUpsertAsync(fasterKV, fasterSession, currentCtx, pendingContext, flushTask, token);