/// <summary> /// Executes a put operation, while providing the logic to retrieve the bytes that were put through a RecordingStream. /// RecordingStream makes it possible to see the actual bytes that are being read by the inner ContentSession. /// </summary> private async Task <PutResult> PutCoreAsync( OperationContext context, Func <IDecoratedStreamContentSession, Func <Stream, Stream>, Task <PutResult> > putRecordedAsync, Func <IContentSession, Task <PutResult> > putAsync) { PutResult result; if (ContentLocationStore.AreBlobsSupported && Inner is IDecoratedStreamContentSession decoratedStreamSession) { RecordingStream recorder = null; result = await putRecordedAsync(decoratedStreamSession, stream => { if (stream.CanSeek && stream.Length <= ContentLocationStore.MaxBlobSize) { recorder = new RecordingStream(inner: stream, size: stream.Length); return(recorder); } return(stream); }); if (result && recorder != null) { // Fire and forget since this step is optional. await ContentLocationStore.PutBlobAsync(context, result.ContentHash, recorder.RecordedBytes).FireAndForgetAndReturnTask(context); } } else { result = await putAsync(Inner); } return(await RegisterPutAsync(context, context.Token, UrgencyHint.Nominal, result)); }
/// <summary> /// Executes a put operation, while providing the logic to retrieve the bytes that were put through a RecordingStream. /// RecordingStream makes it possible to see the actual bytes that are being read by the inner ContentSession. /// </summary> private async Task <PutResult> PutCoreAsync( OperationContext context, Func <IDecoratedStreamContentSession, Func <Stream, Stream>, Task <PutResult> > putRecordedAsync, Func <IContentSession, Task <PutResult> > putAsync, string path = null) { PutResult result; bool putBlob = false; if (ContentLocationStore.AreBlobsSupported && Inner is IDecoratedStreamContentSession decoratedStreamSession) { RecordingStream recorder = null; result = await putRecordedAsync(decoratedStreamSession, stream => { if (stream.CanSeek && stream.Length <= ContentLocationStore.MaxBlobSize) { recorder = new RecordingStream(inner: stream, size: stream.Length); return(recorder); } return(stream); }); if (result && recorder != null) { // Fire and forget since this step is optional. var putBlobResult = await ContentLocationStore.PutBlobAsync(context, result.ContentHash, recorder.RecordedBytes); putBlob = putBlobResult.Succeeded; } } else { result = await putAsync(Inner); } if (!result) { return(result); } // It is important to register location before requesting the proactive copy; otherwise, we can fail the proactive copy. var registerResult = await RegisterPutAsync(context, UrgencyHint.Nominal, result); // Only perform proactive copy to other machines if we didn't put the blob into Redis and we succeeded in registering our location. if (!putBlob && registerResult && Settings.ProactiveCopyMode != ProactiveCopyMode.Disabled) { // Since the rest of the operation is done asynchronously, create new context to stop cancelling operation prematurely. WithOperationContext( context, CancellationToken.None, operationContext => RequestProactiveCopyIfNeededAsync(operationContext, result.ContentHash, path) ).FireAndForget(context); } return(registerResult); }
/// <summary> /// Executes a put operation, while providing the logic to retrieve the bytes that were put through a RecordingStream. /// RecordingStream makes it possible to see the actual bytes that are being read by the inner ContentSession. /// </summary> private async Task <PutResult> PutCoreAsync( OperationContext context, Func <IDecoratedStreamContentSession, Func <Stream, Stream>, Task <PutResult> > putRecordedAsync, Func <IContentSession, Task <PutResult> > putAsync) { PutResult result; if (ContentLocationStore.AreBlobsSupported && Inner is IDecoratedStreamContentSession decoratedStreamSession) { RecordingStream recorder = null; result = await putRecordedAsync(decoratedStreamSession, stream => { if (stream.CanSeek && stream.Length <= ContentLocationStore.MaxBlobSize) { recorder = new RecordingStream(inner: stream, size: stream.Length); return(recorder); } return(stream); }); if (result && recorder != null) { // Fire and forget since this step is optional. await ContentLocationStore.PutBlobAsync(context, result.ContentHash, recorder.RecordedBytes).FireAndForgetAndReturnTask(context); } } else { result = await putAsync(Inner); } var putResult = await RegisterPutAsync(context, UrgencyHint.Nominal, result); if (putResult.Succeeded && Settings.EnableProactiveCopy) { // Since the rest of the operation is done asynchronously, create new context to stop cancelling operation prematurely. WithOperationContext( context, CancellationToken.None, operationContext => RequestProactiveCopyIfNeededAsync(operationContext, putResult.ContentHash) ).FireAndForget(context); } return(putResult); }
/// <summary> /// Executes a put operation, while providing the logic to retrieve the bytes that were put through a RecordingStream. /// RecordingStream makes it possible to see the actual bytes that are being read by the inner ContentSession. /// </summary> private async Task <PutResult> PutCoreAsync( OperationContext context, Func <IDecoratedStreamContentSession, Func <Stream, Stream>, Task <PutResult> > putRecordedAsync, Func <IContentSession, Task <PutResult> > putAsync, string path = null) { PutResult result; if (ContentLocationStore.AreBlobsSupported && Inner is IDecoratedStreamContentSession decoratedStreamSession) { RecordingStream recorder = null; result = await putRecordedAsync(decoratedStreamSession, stream => { if (stream.CanSeek && stream.Length <= ContentLocationStore.MaxBlobSize) { recorder = RecordingStream.ReadRecordingStream(inner: stream, size: stream.Length); return(recorder); } return(stream); }); if (result && recorder != null) { await PutBlobAsync(context, result.ContentHash, recorder.RecordedBytes); } } else { result = await putAsync(Inner); } if (!result) { return(result); } // It is important to register location before requesting the proactive copy; otherwise, we can fail the proactive copy. var registerResult = await RegisterPutAsync(context, UrgencyHint.Nominal, result); // Only perform proactive copy to other machines if we succeeded in registering our location. if (registerResult && Settings.ProactiveCopyOnPut && Settings.ProactiveCopyMode != ProactiveCopyMode.Disabled) { // Since the rest of the operation is done asynchronously, create new context to stop cancelling operation prematurely. var proactiveCopyTask = WithOperationContext( context, CancellationToken.None, operationContext => ProactiveCopyIfNeededAsync(operationContext, result.ContentHash, tryBuildRing: true, ProactiveCopyReason.Put, path) ); if (Settings.InlineProactiveCopies) { var proactiveCopyResult = await proactiveCopyTask; // Only fail if all copies failed. if (!proactiveCopyResult.Succeeded && proactiveCopyResult.RingCopyResult?.Succeeded == false && proactiveCopyResult.OutsideRingCopyResult?.Succeeded == false) { return(new PutResult(proactiveCopyResult)); } } else { // Tracing task-related errors because normal failures already traced by the operation provider proactiveCopyTask.TraceIfFailure(context, failureSeverity: Severity.Debug, traceTaskExceptionsOnly: true, operation: "ProactiveCopyIfNeeded"); } } return(registerResult); }