Beispiel #1
0
        public override int Read(char[] buffer, int index, int count)
        {
            ValidateReadParameters(buffer, index, count);

            if (IsClosed)
            {
                throw ADP.ObjectDisposed(this);
            }
            if (_currentTask != null)
            {
                throw ADP.AsyncOperationPending();
            }

            int charsRead   = 0;
            int charsNeeded = count;

            // Load in peeked char
            if ((charsNeeded > 0) && (HasPeekedChar))
            {
                Debug.Assert((_peekedChar >= char.MinValue) && (_peekedChar <= char.MaxValue), $"Bad peeked character: {_peekedChar}");
                buffer[index + charsRead] = (char)_peekedChar;
                charsRead++;
                charsNeeded--;
                _peekedChar = -1;
            }

            // If we need more data and there is data avaiable, read
            charsRead += InternalRead(buffer, index + charsRead, charsNeeded);

            return(charsRead);
        }
Beispiel #2
0
        public override int Read()
        {
            if (_currentTask != null)
            {
                throw ADP.AsyncOperationPending();
            }
            if (IsClosed)
            {
                throw ADP.ObjectDisposed(this);
            }

            int readChar = -1;

            // If there is already a peeked char, then return it
            if (HasPeekedChar)
            {
                readChar    = _peekedChar;
                _peekedChar = -1;
            }
            // If there is data available try to read a char
            else
            {
                char[] tempBuffer = new char[1];
                int    charsRead  = InternalRead(tempBuffer, 0, 1);
                if (charsRead == 1)
                {
                    readChar = tempBuffer[0];
                }
            }

            Debug.Assert(readChar == -1 || ((readChar >= char.MinValue) && (readChar <= char.MaxValue)), $"Bad read character: {readChar}");
            return(readChar);
        }
Beispiel #3
0
        public override int Peek()
        {
            if (_currentTask != null)
            {
                throw ADP.AsyncOperationPending();
            }
            if (IsClosed)
            {
                throw ADP.ObjectDisposed(this);
            }

            if (!HasPeekedChar)
            {
                _peekedChar = Read();
            }

            Debug.Assert(_peekedChar == -1 || ((_peekedChar >= char.MinValue) && (_peekedChar <= char.MaxValue)), $"Bad peeked character: {_peekedChar}");
            return(_peekedChar);
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            ValidateReadParameters(buffer, offset, count);
            if (!CanRead)
            {
                throw ADP.ObjectDisposed(this);
            }
            if (_currentTask != null)
            {
                throw ADP.AsyncOperationPending();
            }

            try
            {
                return(_reader.GetBytesInternalSequential(_columnIndex, buffer, offset, count, _readTimeout));
            }
            catch (SqlException ex)
            {
                // Stream.Read() can't throw a SqlException - so wrap it in an IOException
                throw ADP.ErrorReadingFromStream(ex);
            }
        }
Beispiel #5
0
        public override Task <int> ReadAsync(char[] buffer, int index, int count)
        {
            ValidateReadParameters(buffer, index, count);
            TaskCompletionSource <int> completion = new TaskCompletionSource <int>();

            if (IsClosed)
            {
                completion.SetException(ADP.ExceptionWithStackTrace(ADP.ObjectDisposed(this)));
            }
            else
            {
                try
                {
                    Task original = Interlocked.CompareExchange <Task>(ref _currentTask, completion.Task, null);
                    if (original != null)
                    {
                        completion.SetException(ADP.ExceptionWithStackTrace(ADP.AsyncOperationPending()));
                    }
                    else
                    {
                        bool completedSynchronously = true;
                        int  charsRead     = 0;
                        int  adjustedIndex = index;
                        int  charsNeeded   = count;

                        // Load in peeked char
                        if ((HasPeekedChar) && (charsNeeded > 0))
                        {
                            // Take a copy of _peekedChar in case it is cleared during close
                            int peekedChar = _peekedChar;
                            if (peekedChar >= char.MinValue)
                            {
                                Debug.Assert((_peekedChar >= char.MinValue) && (_peekedChar <= char.MaxValue), $"Bad peeked character: {_peekedChar}");
                                buffer[adjustedIndex] = (char)peekedChar;
                                adjustedIndex++;
                                charsRead++;
                                charsNeeded--;
                                _peekedChar = -1;
                            }
                        }

                        int    byteBufferUsed;
                        byte[] byteBuffer = PrepareByteBuffer(charsNeeded, out byteBufferUsed);

                        // Permit a 0 byte read in order to advance the reader to the correct column
                        if ((byteBufferUsed < byteBuffer.Length) || (byteBuffer.Length == 0))
                        {
                            int bytesRead;
                            var reader = _reader;
                            if (reader != null)
                            {
                                Task <int> getBytesTask = reader.GetBytesAsync(_columnIndex, byteBuffer, byteBufferUsed, byteBuffer.Length - byteBufferUsed, Timeout.Infinite, _disposalTokenSource.Token, out bytesRead);
                                if (getBytesTask == null)
                                {
                                    byteBufferUsed += bytesRead;
                                }
                                else
                                {
                                    // We need more data - setup the callback, and mark this as not completed sync
                                    completedSynchronously = false;
                                    getBytesTask.ContinueWith((t) =>
                                    {
                                        _currentTask = null;
                                        // If we completed but the textreader is closed, then report cancellation
                                        if ((t.Status == TaskStatus.RanToCompletion) && (!IsClosed))
                                        {
                                            try
                                            {
                                                int bytesReadFromStream = t.Result;
                                                byteBufferUsed         += bytesReadFromStream;
                                                if (byteBufferUsed > 0)
                                                {
                                                    charsRead += DecodeBytesToChars(byteBuffer, byteBufferUsed, buffer, adjustedIndex, charsNeeded);
                                                }
                                                completion.SetResult(charsRead);
                                            }
                                            catch (Exception ex)
                                            {
                                                completion.SetException(ex);
                                            }
                                        }
                                        else if (IsClosed)
                                        {
                                            completion.SetException(ADP.ExceptionWithStackTrace(ADP.ObjectDisposed(this)));
                                        }
                                        else if (t.Status == TaskStatus.Faulted)
                                        {
                                            if (t.Exception.InnerException is SqlException)
                                            {
                                                // ReadAsync can't throw a SqlException, so wrap it in an IOException
                                                completion.SetException(ADP.ExceptionWithStackTrace(ADP.ErrorReadingFromStream(t.Exception.InnerException)));
                                            }
                                            else
                                            {
                                                completion.SetException(t.Exception.InnerException);
                                            }
                                        }
                                        else
                                        {
                                            completion.SetCanceled();
                                        }
                                    }, TaskScheduler.Default);
                                }


                                if ((completedSynchronously) && (byteBufferUsed > 0))
                                {
                                    // No more data needed, decode what we have
                                    charsRead += DecodeBytesToChars(byteBuffer, byteBufferUsed, buffer, adjustedIndex, charsNeeded);
                                }
                            }
                            else
                            {
                                // Reader is null, close must of happened in the middle of this read
                                completion.SetException(ADP.ExceptionWithStackTrace(ADP.ObjectDisposed(this)));
                            }
                        }


                        if (completedSynchronously)
                        {
                            _currentTask = null;
                            if (IsClosed)
                            {
                                completion.SetCanceled();
                            }
                            else
                            {
                                completion.SetResult(charsRead);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    // In case of any errors, ensure that the completion is completed and the task is set back to null if we switched it
                    completion.TrySetException(ex);
                    Interlocked.CompareExchange(ref _currentTask, null, completion.Task);
                    throw;
                }
            }

            return(completion.Task);
        }
        public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            ValidateReadParameters(buffer, offset, count);

            TaskCompletionSource <int> completion = new TaskCompletionSource <int>();

            if (!CanRead)
            {
                completion.SetException(ADP.ExceptionWithStackTrace(ADP.ObjectDisposed(this)));
            }
            else
            {
                try
                {
                    Task original = Interlocked.CompareExchange <Task>(ref _currentTask, completion.Task, null);
                    if (original != null)
                    {
                        completion.SetException(ADP.ExceptionWithStackTrace(ADP.AsyncOperationPending()));
                    }
                    else
                    {
                        // Set up a combined cancellation token for both the user's and our disposal tokens
                        CancellationTokenSource combinedTokenSource;
                        if (!cancellationToken.CanBeCanceled)
                        {
                            // Users token is not cancellable - just use ours
                            combinedTokenSource = _disposalTokenSource;
                        }
                        else
                        {
                            // Setup registrations from user and disposal token to cancel the combined token
                            combinedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _disposalTokenSource.Token);
                        }

                        int        bytesRead    = 0;
                        Task <int> getBytesTask = null;
                        var        reader       = _reader;
                        if ((reader != null) && (!cancellationToken.IsCancellationRequested) && (!_disposalTokenSource.Token.IsCancellationRequested))
                        {
                            getBytesTask = reader.GetBytesAsync(_columnIndex, buffer, offset, count, _readTimeout, combinedTokenSource.Token, out bytesRead);
                        }

                        if (getBytesTask == null)
                        {
                            _currentTask = null;
                            if (cancellationToken.IsCancellationRequested)
                            {
                                completion.SetCanceled();
                            }
                            else if (!CanRead)
                            {
                                completion.SetException(ADP.ExceptionWithStackTrace(ADP.ObjectDisposed(this)));
                            }
                            else
                            {
                                completion.SetResult(bytesRead);
                            }

                            if (combinedTokenSource != _disposalTokenSource)
                            {
                                combinedTokenSource.Dispose();
                            }
                        }
                        else
                        {
                            getBytesTask.ContinueWith((t) =>
                            {
                                _currentTask = null;
                                // If we completed, but _reader is null (i.e. the stream is closed), then report cancellation
                                if ((t.Status == TaskStatus.RanToCompletion) && (CanRead))
                                {
                                    completion.SetResult((int)t.Result);
                                }
                                else if (t.Status == TaskStatus.Faulted)
                                {
                                    if (t.Exception.InnerException is SqlException)
                                    {
                                        // Stream.ReadAsync() can't throw a SqlException - so wrap it in an IOException
                                        completion.SetException(ADP.ExceptionWithStackTrace(ADP.ErrorReadingFromStream(t.Exception.InnerException)));
                                    }
                                    else
                                    {
                                        completion.SetException(t.Exception.InnerException);
                                    }
                                }
                                else if (!CanRead)
                                {
                                    completion.SetException(ADP.ExceptionWithStackTrace(ADP.ObjectDisposed(this)));
                                }
                                else
                                {
                                    completion.SetCanceled();
                                }

                                if (combinedTokenSource != _disposalTokenSource)
                                {
                                    combinedTokenSource.Dispose();
                                }
                            }, TaskScheduler.Default);
                        }
                    }
                }
                catch (Exception ex)
                {
                    // In case of any errors, ensure that the completion is completed and the task is set back to null if we switched it
                    completion.TrySetException(ex);
                    Interlocked.CompareExchange(ref _currentTask, null, completion.Task);
                    throw;
                }
            }

            return(completion.Task);
        }