Exemple #1
0
        public WaitHandle WriteAsync(Block block, long offset, Action <IAsyncResult <Block> > callback, CancellationToken cancellationToken)
        {
            ThrowIf.Argument.IsNull(block, nameof(block));
            ThrowIf.Argument.LessThanZero(offset, nameof(offset));
            ThrowIf.Argument.IsNull(callback, nameof(callback));

            if (block.Index == -1)
            {
                var wh = new ManualResetEvent(initialState: true);
                callback(new ValueResult <Block>(block, wh));

                return(wh);
            }

            var waitHandle = new ManualResetEvent(initialState: false);
            Action <States, CancellationToken> writerStateMachine = null;
            Exception exception = null;

            writerStateMachine = (state, token) => {
                if (token.IsCancellationRequested)
                {
                    waitHandle.Set();
                    return;
                }

                switch (state)
                {
                case States.Start:
                    try {
                        WriteBlock(block.Payload, offset, block.Size);
                        _scheduler.ScheduleWorkItem(() => writerStateMachine(States.Success, token));
                    } catch (Exception ex) {
                        exception = ex;
                        _scheduler.ScheduleWorkItem(() => writerStateMachine(States.Error, token));
                    }
                    break;

                case States.Success:
                    callback(new ValueResult <Block>(block, waitHandle));
                    _scheduler.ScheduleWorkItem(() => writerStateMachine(States.Finalize, CancellationToken.None));
                    break;

                case States.Error:
                    callback(new ExceptionResult <Block>(exception, waitHandle));
                    _scheduler.ScheduleWorkItem(() => writerStateMachine(States.Finalize, CancellationToken.None));
                    break;

                case States.Finalize:
                    RemoveAwaiter(waitHandle);
                    waitHandle.Set();
                    break;

                default: throw new ArgumentOutOfRangeException($"Unknown state: {state}");
                }
            };
            _scheduler.ScheduleWorkItem(() => writerStateMachine(States.Start, cancellationToken));
            StoreAwaiter(waitHandle);

            return(waitHandle);
        }
Exemple #2
0
        public WaitHandle ReadAsync(Action <IAsyncResult <Block> > callback, CancellationToken cancellationToken = default)
        {
            ThrowIf.Argument.IsNull(callback, nameof(callback));

            var waitHandle = new ManualResetEvent(initialState: false);
            Action <int, CancellationToken> readStateMachine = null;
            Exception exception = null;
            Block     block     = null;

            readStateMachine = (state, token) => {
                switch (state)
                {
                case 0:
                    if (_isFaulted)
                    {
                        exception = new AggregateException(GetExceptions());
                        _scheduler.ScheduleWorkItem(() => readStateMachine(4, CancellationToken.None));

                        return;
                    }

                    // try to get block
                    if (TryDequeue(out Block _block))
                    {
                        block = _block;
                        _scheduler.ScheduleWorkItem(() => readStateMachine(1, token));

                        return;
                    }

                    if (_endOfStream)
                    {
                        _scheduler.ScheduleWorkItem(() => readStateMachine(3, token));
                    }
                    else
                    {
                        _scheduler.ScheduleWorkItem(() => readStateMachine(2, token));
                    }
                    break;

                case 1:     // success
                    callback(new ValueResult <Block>(block, waitHandle));
                    _scheduler.ScheduleWorkItem(
                        workItem: () => readStateMachine(5, CancellationToken.None));
                    break;

                case 2:     // retry
                    _scheduler.ScheduleWorkItem(() => readStateMachine(0, token));
                    break;

                case 3:     // end of steam
                    callback(new ValueResult <Block>(Block.NullBlock(), waitHandle));
                    _scheduler.ScheduleWorkItem(
                        workItem: () => readStateMachine(5, CancellationToken.None));
                    break;

                case 4:     // exception
                    callback(new ExceptionResult <Block>(exception, waitHandle));
                    _scheduler.ScheduleWorkItem(
                        workItem: () => readStateMachine(5, CancellationToken.None));
                    break;

                case 5:     // finalizing
                    waitHandle.Set();
                    break;
                }
            };

            _scheduler.ScheduleWorkItem(() => readStateMachine(0, cancellationToken));

            return(waitHandle);
        }
Exemple #3
0
        public void Start(CancellationToken cancellationToken)
        {
            Action <States, CancellationToken> archStateMachine = null;

            archStateMachine = (state, token) => {
                if (token.IsCancellationRequested)
                {
                    //TODO: try to delete target file.
                    IsCancelled = true;
                    _waitHandle.Set();
                    return;
                }

                switch (state)
                {
                case States.Start:
                    Interlocked.Increment(ref _readRequestCount);
                    _reader.ReadAsync(asyncBlockResult => {
                        try {
                            var block = asyncBlockResult.Result;
                            if (block.Index >= 0)
                            {
                                AddToBuffer(block);
                                _scheduler.ScheduleWorkItem(() => archStateMachine(States.Write, token));
                                _scheduler.ScheduleWorkItem(() => archStateMachine(States.NextItem, token));
                            }
                            else
                            {
                                _scheduler.ScheduleWorkItem(() => archStateMachine(States.EndOfSteam, token));
                            }
                        } catch (Exception ex) {
                            SetException(ex);
                            _scheduler.ScheduleWorkItem(() => archStateMachine(States.Error, token));
                        } finally {
                            Interlocked.Decrement(ref _readRequestCount);
                        }
                    }, token);
                    break;

                case States.Write:
                    if (TryGetNextBlock(out Block block, out long offset))
                    {
                        Interlocked.Increment(ref _writeRequestCount);
                        _writer.WriteAsync(block, offset, asyncBlockResult => {
                            try {
                                var block = asyncBlockResult.Result;
                            }catch (Exception ex) {
                                SetException(ex);
                                _scheduler.ScheduleWorkItem(() => archStateMachine(States.Error, token));
                            } finally {
                                Interlocked.Decrement(ref _writeRequestCount);
                            }
                        }, token);
                    }
                    break;

                case States.NextItem:
                    archStateMachine(States.Start, cancellationToken);
                    break;

                case States.EndOfSteam:
                    _endOfStream = true;
                    if (_readRequestCount != 0 || _writeRequestCount != 0 || _buffer.Count > 0)
                    {
                        _scheduler.ScheduleWorkItem(() => archStateMachine(States.EndOfSteam, token));     // wait spinner
                    }
                    else
                    {
                        _scheduler.ScheduleWorkItem(() => archStateMachine(States.Finalize, CancellationToken.None));
                    }
                    break;

                case States.Error:
                    //SetException(exception);
                    _scheduler.ScheduleWorkItem(() => archStateMachine(States.Finalize, CancellationToken.None));
                    break;

                case States.Finalize:
                    _waitHandle.Set();
                    break;

                default: throw new ArgumentOutOfRangeException($"Unknown state: {state}");
                }
            };
            _scheduler.ScheduleWorkItem(() => archStateMachine(States.Start, cancellationToken));
        }
Exemple #4
0
        public WaitHandle ReadAsync(Action <IAsyncResult <Block> > callback, CancellationToken cancellationToken)
        {
            var waitHandle = new ManualResetEvent(initialState: false);
            Action <int, CancellationToken> readStateMachine = null;
            Block     block     = null;
            Exception exception = null;

            readStateMachine = (state, token) => {
                if (token.IsCancellationRequested)
                {
                    RemoveAwaiter(waitHandle);
                    waitHandle.Set();

                    callback(new OperationCancelledResult <Block>(waitHandle));
                    return;
                }

                switch (state)
                {
                case 0:
                    var blockIdx = GetNextBlockIndex();
                    var offset   = (long)blockIdx * _blockSizeInBytes;
                    _scheduler.ScheduleWorkItem(
                        workItem: () => {
                        try {
                            block = ReadBlock(blockIdx, offset);
                        } catch (Exception ex) {
                            exception = ex;
                        }
                    },
                        callback: () => {
                        if (block != null)
                        {
                            readStateMachine(1, token);
                        }
                        else
                        {
                            readStateMachine(2, token);
                        }
                    });

                    break;

                case 1:     // success
                    _scheduler.ScheduleWorkItem(
                        workItem: () => callback(new ValueResult <Block>(block, waitHandle)),
                        callback: () => readStateMachine(3, token));
                    break;

                case 2:     // exception
                    _scheduler.ScheduleWorkItem(
                        workItem: () => callback(new ExceptionResult <Block>(exception, waitHandle)),
                        callback: () => readStateMachine(3, token));
                    break;

                case 3:     // finalizing
                    RemoveAwaiter(waitHandle);
                    waitHandle.Set();
                    break;
                }
            };


            StoreAwaiter(waitHandle);
            _scheduler.ScheduleWorkItem(() => readStateMachine(0, cancellationToken), callback: null);

            return(waitHandle);
        }
Exemple #5
0
        public WaitHandle ReadAsync(Action <IAsyncResult <Block> > callback, CancellationToken cancellationToken)
        {
            var waitHandle = new ManualResetEvent(initialState: false);

            Action <States, CancellationToken> readerStateMachine = null;
            Block     block           = null;
            Block     compressedBlock = null;
            Exception exception       = null;

            readerStateMachine = (state, token) => {
                switch (state)
                {
                case States.Start:
                    _reader.ReadAsync(blockAsyncResult => {
                        try {
                            block = blockAsyncResult.Result;
                            if (block.Index >= 0)
                            {
                                _scheduler.ScheduleWorkItem(() => readerStateMachine(States.Compress, token));
                            }
                            else
                            {
                                _scheduler.ScheduleWorkItem(() => readerStateMachine(States.EndOfStream, token));
                            }
                        } catch (Exception ex) {
                            exception = ex;
                            _scheduler.ScheduleWorkItem(() => readerStateMachine(States.Error, token));
                        }
                    }, token);
                    break;

                case States.EndOfStream:
                    callback(new ValueResult <Block>(block, waitHandle));
                    _scheduler.ScheduleWorkItem(() => readerStateMachine(States.Finalize, CancellationToken.None));
                    break;

                case States.Compress:     // compress
                    try {
                        int    size;
                        byte[] data;
                        (size, data)    = CompressBlock(block.Payload, block.Size, _compressionLevel);
                        compressedBlock = new Block(block.Index, block.Capacity, data, size);

                        _scheduler.ScheduleWorkItem(() => readerStateMachine(States.Success, token));
                    } catch (Exception ex) {
                        exception = ex;
                        _scheduler.ScheduleWorkItem(() => readerStateMachine(States.Error, token));
                    }
                    break;

                case States.Success:     // success
                    callback(new ValueResult <Block>(compressedBlock, waitHandle));
                    _scheduler.ScheduleWorkItem(() => readerStateMachine(States.Finalize, CancellationToken.None));
                    break;

                case States.Error:     // error
                    callback(new ExceptionResult <Block>(exception, waitHandle));
                    _scheduler.ScheduleWorkItem(() => readerStateMachine(States.Finalize, CancellationToken.None));
                    break;

                case States.Finalize:     // finalize
                    waitHandle.Set();
                    break;
                }
            };
            _scheduler.ScheduleWorkItem(() => readerStateMachine(0, cancellationToken));

            return(waitHandle);
        }