Пример #1
0
        /// <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));
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        /// <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);
        }