Пример #1
0
        private static async ValueTask <ReadAsyncResult <Input, Output, Context, Functions> > SlowReadAsync <Input, Output, Context, Functions>(
            FasterKV <Key, Value> @this,
            ClientSession <Key, Value, Input, Output, Context, Functions> clientSession,
            PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, CancellationToken token = default)
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            clientSession.ctx.asyncPendingCount++;
            clientSession.ctx.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;
            }
            catch (Exception e)
            {
                exceptionDispatchInfo = ExceptionDispatchInfo.Capture(e);
            }

            return(new ReadAsyncResult <Input, Output, Context, Functions>(@this, clientSession, pendingContext, diskRequest, exceptionDispatchInfo));
        }
Пример #2
0
        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));
        }
Пример #3
0
        private static async ValueTask <ReadAsyncResult <Input, Output, Context, Functions> > SlowReadAsync <Input, Output, Context, Functions>(
            FasterKV <Key, Value> @this,
            ClientSession <Key, Value, Input, Output, Context, Functions> clientSession,
            PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, CancellationToken token = default)
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            clientSession.ctx.asyncPendingCount++;
            clientSession.ctx.pendingReads.Add();

            try
            {
                token.ThrowIfCancellationRequested();

                if (@this.epoch.ThisInstanceProtected())
                {
                    throw new NotSupportedException("Async operations not supported over protected epoch");
                }

                diskRequest = await diskRequest.asyncOperation.Task;
            }
            catch
            {
                clientSession.ctx.ioPendingRequests.Remove(pendingContext.id);
                clientSession.ctx.asyncPendingCount--;
                throw;
            }
            finally
            {
                clientSession.ctx.pendingReads.Remove();
            }

            return(new ReadAsyncResult <Input, Output, Context, Functions>(@this, clientSession, pendingContext, diskRequest));
        }
Пример #4
0
            internal async ValueTask <RmwAsyncResult <Input, Output, Context> > CompleteAsync(CancellationToken token = default)
            {
                Debug.Assert(_fasterKV.RelaxedCPR);

                AsyncIOContext <Key, Value> newDiskRequest = default;

                if ((_diskRequest.asyncOperation != null || _flushTask is { }) &&
Пример #5
0
 internal ReadAsyncResult(Status status, Output output)
 {
     _exception      = default;
     _result         = (status, output);
     _fasterKV       = default;
     _clientSession  = default;
     _pendingContext = default;
     _diskRequest    = default;
 }
Пример #6
0
 internal ReadAsyncResult(
     FasterKV <Key, Value, Input, Output, Context, Functions> fasterKV,
     ClientSession <Key, Value, Input, Output, Context, Functions> clientSession,
     PendingContext pendingContext, AsyncIOContext <Key, Value> diskRequest)
 {
     status            = Status.PENDING;
     output            = default;
     readAsyncInternal = new ReadAsyncInternal(fasterKV, clientSession, pendingContext, diskRequest);
 }
Пример #7
0
 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));
 }
Пример #8
0
 internal ReadAsyncInternal(FasterKV <Key, Value, Input, Output, Context, Functions> fasterKV, ClientSession <Key, Value, Input, Output, Context, Functions> clientSession, PendingContext pendingContext, AsyncIOContext <Key, Value> diskRequest)
 {
     _exception              = default;
     _fasterKV               = fasterKV;
     _clientSession          = clientSession;
     _pendingContext         = pendingContext;
     _diskRequest            = diskRequest;
     CompletionComputeStatus = Pending;
 }
Пример #9
0
 internal RmwAsyncResult(
     FasterKV <Key, Value> fasterKV,
     ClientSession <Key, Value, Input, Output, Context, Functions> clientSession,
     PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, ExceptionDispatchInfo exceptionDispatchInfo)
 {
     status           = Status.PENDING;
     output           = default;
     rmwAsyncInternal = new RmwAsyncInternal <Input, Output, Context, Functions>(fasterKV, clientSession, pendingContext, diskRequest, exceptionDispatchInfo);
 }
Пример #10
0
 internal RmwAsyncInternal(FasterKV <Key, Value> fasterKV, ClientSession <Key, Value, Input, Output, Context, Functions> clientSession, PendingContext <Input, Output, Context> pendingContext, AsyncIOContext <Key, Value> diskRequest, ExceptionDispatchInfo exceptionDispatchInfo)
 {
     _exception              = exceptionDispatchInfo;
     _fasterKV               = fasterKV;
     _clientSession          = clientSession;
     _pendingContext         = pendingContext;
     _diskRequest            = diskRequest;
     CompletionComputeStatus = Pending;
 }
Пример #11
0
            internal ValueTask <RmwAsyncResult <Input, Output, Context, Functions> > CompleteAsync(CancellationToken token = default)
            {
                Debug.Assert(_fasterKV.RelaxedCPR);

                AsyncIOContext <Key, Value> newDiskRequest = default;

                if (_diskRequest.asyncOperation != null &&
                    CompletionComputeStatus != Completed &&
                    Interlocked.CompareExchange(ref CompletionComputeStatus, Completed, Pending) == Pending)
                {
                    try
                    {
                        if (_exception == default)
                        {
                            if (_clientSession.SupportAsync)
                            {
                                _clientSession.UnsafeResumeThread();
                            }
                            try
                            {
                                var status = _fasterKV.InternalCompletePendingRequestFromContext(_clientSession.ctx, _clientSession.ctx, _clientSession.FasterSession, _diskRequest, ref _pendingContext, true, out newDiskRequest);
                                _pendingContext.Dispose();
                                if (status != Status.PENDING)
                                {
                                    return(new ValueTask <RmwAsyncResult <Input, Output, Context, Functions> >(new RmwAsyncResult <Input, Output, Context, Functions>(status, default)));
                                }
                            }
                            finally
                            {
                                if (_clientSession.SupportAsync)
                                {
                                    _clientSession.UnsafeSuspendThread();
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        _exception = ExceptionDispatchInfo.Capture(e);
                    }
                    finally
                    {
                        _clientSession.ctx.ioPendingRequests.Remove(_pendingContext.id);
                        _clientSession.ctx.asyncPendingCount--;
                        _clientSession.ctx.pendingReads.Remove();
                    }
                }

                if (_exception != default)
                {
                    _exception.Throw();
                }

                return(SlowRmwAsync(_fasterKV, _clientSession, _pendingContext, newDiskRequest, token));
            }
Пример #12
0
 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);
 }
Пример #13
0
 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;
 }
Пример #14
0
        private bool RetrievedObjects(byte *record, AsyncIOContext ctx)
        {
            if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize())
            {
                return(true);
            }

            if (ctx.objBuffer.buffer == null)
            {
                // Issue IO for objects
                long startAddress = -1;
                long numBytes     = 0;
                if (Key.HasObjectsToSerialize())
                {
                    var x = (AddressInfo *)Layout.GetKey((long)record);
                    numBytes    += x->Size;
                    startAddress = x->Address;
                }

                if (Value.HasObjectsToSerialize())
                {
                    var x = (AddressInfo *)Layout.GetValue((long)record);
                    numBytes += x->Size;
                    if (startAddress == -1)
                    {
                        startAddress = x->Address;
                    }
                }

                // We are limited to a 2GB size per key-value
                if (numBytes > int.MaxValue)
                {
                    throw new Exception("Size of key-value exceeds max of 2GB: " + numBytes);
                }

                AsyncGetFromDisk(startAddress, (int)numBytes,
                                 AsyncGetFromDiskCallback, ctx, ctx.record);
                return(false);
            }

            // Parse the key and value objects
            MemoryStream ms = new MemoryStream(ctx.objBuffer.buffer);

            ms.Seek(ctx.objBuffer.offset + ctx.objBuffer.valid_offset, SeekOrigin.Begin);
            Key.Deserialize(Layout.GetKey((long)record), ms);
            Value.Deserialize(Layout.GetValue((long)record), ms);
            ctx.objBuffer.Return();
            return(true);
        }
Пример #15
0
        private bool RetrievedObjects(byte *record, AsyncIOContext ctx)
        {
            if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize())
            {
                return(true);
            }

            if (ctx.objBuffer.buffer == null)
            {
                // Issue IO for objects
                long startAddress = -1;
                int  numBytes     = 0;
                if (Key.HasObjectsToSerialize())
                {
                    var x = (AddressInfo *)Layout.GetKey((long)record);
                    if (x->IsDiskAddress)
                    {
                        numBytes    += x->Size;
                        startAddress = x->Address;
                    }
                }

                if (Value.HasObjectsToSerialize())
                {
                    var x = (AddressInfo *)Layout.GetValue((long)record);
                    if (x->IsDiskAddress)
                    {
                        numBytes += x->Size;
                        if (startAddress == -1)
                        {
                            startAddress = x->Address;
                        }
                    }
                }

                AsyncGetFromDisk(startAddress, numBytes,
                                 AsyncGetFromDiskCallback, ctx, ctx.record);
                return(false);
            }

            // Parse the key and value objects
            MemoryStream ms = new MemoryStream(ctx.objBuffer.buffer);

            ms.Seek(ctx.objBuffer.offset + ctx.objBuffer.valid_offset, SeekOrigin.Begin);
            Key.Deserialize(Layout.GetKey((long)record), ms);
            Value.Deserialize(Layout.GetValue((long)record), ms);
            ctx.objBuffer.Return();
            return(true);
        }
Пример #16
0
        private void AsyncGetFromDisk(long fromLogical,
                                      int numRecords,
                                      IOCompletionCallback callback,
                                      AsyncIOContext context,
                                      SectorAlignedMemory result = default(SectorAlignedMemory))
        {
            while (numPendingReads > 120)
            {
                Thread.SpinWait(100);

                // Do not protect if we are not already protected
                // E.g., we are in an IO thread
                if (epoch.IsProtected())
                    epoch.ProtectAndDrain();
            }
            Interlocked.Increment(ref numPendingReads);
            hlog.AsyncReadRecordToMemory(fromLogical, numRecords, callback, context, result);
        }
Пример #17
0
        protected void InternalContinuePendingRequestAndCallback(
            ExecutionContext ctx,
            AsyncIOContext request)
        {
            var handleLatches = false;

            if ((ctx.version < threadCtx.version)   // Thread has already shifted to (v+1)
                ||
                (threadCtx.phase == Phase.PREPARE)) // Thread still in version v, but acquired shared-latch
            {
                handleLatches = true;
            }

            if (ctx.ioPendingRequests.TryGetValue(request.id, out PendingContext pendingContext))
            {
                var status         = default(Status);
                var internalStatus = default(OperationStatus);

                // Remove from pending dictionary
                ctx.ioPendingRequests.Remove(request.id);

                // Issue the continue command
                if (pendingContext.type == OperationType.READ)
                {
                    internalStatus = InternalContinuePendingRead(ctx, request, ref pendingContext);
                }
                else
                {
                    internalStatus = InternalContinuePendingRMW(ctx, request, ref pendingContext);;
                }

                // Delete key, value, record
                if (Key.HasObjectsToSerialize())
                {
                    var physicalAddress = (long)request.record.GetValidPointer();
                    Key.Free(Layout.GetKey(physicalAddress));
                }
                if (Value.HasObjectsToSerialize())
                {
                    var physicalAddress = (long)request.record.GetValidPointer();
                    Value.Free(Layout.GetValue(physicalAddress));
                }
                request.record.Return();

                // Handle operation status
                if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND)
                {
                    status = (Status)internalStatus;
                }
                else
                {
                    status = HandleOperationStatus(ctx, pendingContext, internalStatus);
                }

                // If done, callback user code
                if (status == Status.OK || status == Status.NOTFOUND)
                {
                    if (handleLatches)
                    {
                        ReleaseSharedLatch(pendingContext.key);
                    }

                    if (pendingContext.type == OperationType.READ)
                    {
                        Functions.ReadCompletionCallback(pendingContext.key,
                                                         pendingContext.input,
                                                         pendingContext.output,
                                                         pendingContext.userContext,
                                                         status);
                    }
                    else
                    {
                        Functions.RMWCompletionCallback(pendingContext.key,
                                                        pendingContext.input,
                                                        pendingContext.userContext,
                                                        status);
                    }
                }
            }
        }
Пример #18
0
        internal void InternalContinuePendingRequestAndCallback(
            FasterExecutionContext ctx,
            AsyncIOContext <Key, Value> request)
        {
            var handleLatches = false;

            if ((ctx.version < threadCtx.version)   // Thread has already shifted to (v+1)
                ||
                (threadCtx.phase == Phase.PREPARE)) // Thread still in version v, but acquired shared-latch
            {
                handleLatches = true;
            }

            if (ctx.ioPendingRequests.TryGetValue(request.id, out PendingContext pendingContext))
            {
                var status         = default(Status);
                var internalStatus = default(OperationStatus);

                // Remove from pending dictionary
                ctx.ioPendingRequests.Remove(request.id);

                // Issue the continue command
                if (pendingContext.type == OperationType.READ)
                {
                    internalStatus = InternalContinuePendingRead(ctx, request, ref pendingContext);
                }
                else
                {
                    internalStatus = InternalContinuePendingRMW(ctx, request, ref pendingContext);;
                }

                request.record.Return();

                // Handle operation status
                if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND)
                {
                    status = (Status)internalStatus;
                }
                else
                {
                    status = HandleOperationStatus(ctx, pendingContext, internalStatus);
                }

                // If done, callback user code
                if (status == Status.OK || status == Status.NOTFOUND)
                {
                    if (handleLatches)
                    {
                        ReleaseSharedLatch(pendingContext.key);
                    }

                    if (pendingContext.type == OperationType.READ)
                    {
                        functions.ReadCompletionCallback(ref pendingContext.key,
                                                         ref pendingContext.input,
                                                         ref pendingContext.output,
                                                         pendingContext.userContext,
                                                         status);
                    }
                    else
                    {
                        functions.RMWCompletionCallback(ref pendingContext.key,
                                                        ref pendingContext.input,
                                                        pendingContext.userContext,
                                                        status);
                    }
                }
            }
        }
Пример #19
0
 /// <summary>
 /// Retrieve objects from object log
 /// </summary>
 /// <param name="record"></param>
 /// <param name="ctx"></param>
 /// <returns></returns>
 protected override bool RetrievedFullRecord(byte *record, ref AsyncIOContext <Key, Value> ctx)
 {
     ShallowCopy(ref GetKey((long)record), ref ctx.key);
     ShallowCopy(ref GetValue((long)record), ref ctx.value);
     return(true);
 }
Пример #20
0
 /// <summary>
 /// Invoked by users to obtain a record from disk. It uses sector aligned memory to read
 /// the record efficiently into memory.
 /// </summary>
 /// <param name="fromLogical"></param>
 /// <param name="numBytes"></param>
 /// <param name="callback"></param>
 /// <param name="context"></param>
 /// <param name="result"></param>
 protected override void AsyncReadRecordObjectsToMemory(long fromLogical, int numBytes, IOCompletionCallback callback, AsyncIOContext <Key, Value> context, SectorAlignedMemory result = default(SectorAlignedMemory))
 {
     throw new InvalidOperationException("AsyncReadRecordObjectsToMemory invalid for BlittableAllocator");
 }
Пример #21
0
 /// <summary>
 /// Retrieve objects from object log
 /// </summary>
 /// <param name="record"></param>
 /// <param name="ctx"></param>
 /// <returns></returns>
 protected override bool RetrievedFullRecord(byte *record, ref AsyncIOContext <Key, Value> ctx)
 {
     return(true);
 }
Пример #22
0
 internal RmwAsyncOperation(AsyncIOContext <Key, Value> diskRequest) => this.diskRequest = diskRequest;
Пример #23
0
        public void AsyncReadRecordToMemory(long fromLogical, int numRecords, IOCompletionCallback callback, AsyncIOContext context, SectorAlignedMemory result = default(SectorAlignedMemory))
        {
            ulong fileOffset        = (ulong)(AlignedPageSizeBytes * (fromLogical >> LogPageSizeBits) + (fromLogical & PageSizeMask));
            ulong alignedFileOffset = (ulong)(((long)fileOffset / sectorSize) * sectorSize);

            uint alignedReadLength = (uint)((long)fileOffset + numRecords - (long)alignedFileOffset);

            alignedReadLength = (uint)((alignedReadLength + (sectorSize - 1)) & ~(sectorSize - 1));

            var record = readBufferPool.Get((int)alignedReadLength);

            record.valid_offset    = (int)(fileOffset - alignedFileOffset);
            record.available_bytes = (int)(alignedReadLength - (fileOffset - alignedFileOffset));
            record.required_bytes  = numRecords;

            var asyncResult = default(AsyncGetFromDiskResult <AsyncIOContext>);

            asyncResult.context = context;
            if (result.buffer == null)
            {
                asyncResult.context.record = record;
                device.ReadAsync(alignedFileOffset,
                                 (IntPtr)asyncResult.context.record.aligned_pointer,
                                 alignedReadLength,
                                 callback,
                                 asyncResult);
            }
            else
            {
                asyncResult.context.record    = result;
                asyncResult.context.objBuffer = record;
                objlogDevice.ReadAsync(
                    (int)(context.logicalAddress >> LogSegmentSizeBits),
                    alignedFileOffset,
                    (IntPtr)asyncResult.context.objBuffer.aligned_pointer,
                    alignedReadLength,
                    callback,
                    asyncResult);
            }
        }
Пример #24
0
 public override ref Value GetContextRecordValue(ref AsyncIOContext <Key, Value> ctx)
 {
     return(ref GetValue((long)ctx.record.GetValidPointer()));
 }