/// <summary>
        /// Commits the import operation. The writer is unusable after this operation.
        /// </summary>
        public void Commit()
        {
            CheckReady();

            if (InMiddleOfRow)
            {
                Cancel();
                throw new InvalidOperationException("Binary importer closed in the middle of a row, cancelling import.");
            }

            try
            {
                WriteTrailer();
                _buf.Flush();
                _buf.EndCopyMode();

                _connector.SendMessage(CopyDoneMessage.Instance);
                _connector.ReadExpecting <CommandCompleteMessage>();
                _connector.ReadExpecting <ReadyForQueryMessage>();

                _state = ImporterState.Committed;
            }
            catch
            {
                // An exception here will have already broken the connection etc.
                Cleanup();
                throw;
            }
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            CheckDisposed();
            if (!CanRead)
            {
                throw new InvalidOperationException("Stream not open for reading");
            }

            if (_isConsumed)
            {
                return(0);
            }

            if (_leftToReadInDataMsg == 0)
            {
                // We've consumed the current DataMessage (or haven't yet received the first),
                // read the next message
                var msg = _connector.ReadMessage();
                switch (msg.Code)
                {
                case BackendMessageCode.CopyData:
                    _leftToReadInDataMsg = ((CopyDataMessage)msg).Length;
                    break;

                case BackendMessageCode.CopyDone:
                    _connector.ReadExpecting <CommandCompleteMessage>();
                    _connector.ReadExpecting <ReadyForQueryMessage>();
                    _isConsumed = true;
                    return(0);

                default:
                    throw _connector.UnexpectedMessageReceived(msg.Code);
                }
            }

            Debug.Assert(_leftToReadInDataMsg > 0);

            // If our buffer is empty, read in more. Otherwise return whatever is there, even if the
            // user asked for more (normal socket behavior)
            if (_readBuf.ReadBytesLeft == 0)
            {
                _readBuf.ReadMore(false).GetAwaiter().GetResult();
            }

            Debug.Assert(_readBuf.ReadBytesLeft > 0);

            var maxCount = Math.Min(_readBuf.ReadBytesLeft, _leftToReadInDataMsg);

            if (count > maxCount)
            {
                count = maxCount;
            }

            _leftToReadInDataMsg -= count;
            _readBuf.ReadBytes(buffer, offset, count);
            return(count);
        }
Exemple #3
0
            async Task <int> Read(byte[] buffer, int offset, int count, bool async)
            {
                if (_leftToRead == 0)
                {
                    var response = await _connector.ReadExpecting <AuthenticationRequestMessage>(async);

                    if (response.AuthRequestType == AuthenticationRequestType.AuthenticationOk)
                    {
                        throw new AuthenticationCompleteException();
                    }
                    var gssMsg = response as AuthenticationGSSContinueMessage;
                    if (gssMsg == null)
                    {
                        throw new NpgsqlException($"Received unexpected authentication request message {response.AuthRequestType}");
                    }
                    _readBuf    = gssMsg.AuthenticationData;
                    _leftToRead = gssMsg.AuthenticationData.Length;
                    _readPos    = 0;
                    buffer[0]   = 22;
                    buffer[1]   = 1;
                    buffer[2]   = 0;
                    buffer[3]   = (byte)((_leftToRead >> 8) & 0xFF);
                    buffer[4]   = (byte)(_leftToRead & 0xFF);
                    return(5);
                }

                if (count > _leftToRead)
                {
                    throw new NpgsqlException($"NegotiateStream trying to read {count} bytes but according to frame header we only have {_leftToRead} left!");
                }
                count = Math.Min(count, _leftToRead);
                Array.Copy(_readBuf, _readPos, buffer, offset, count);
                _leftToRead -= count;
                return(count);
            }
Exemple #4
0
        void ReadHeader()
        {
            _leftToReadInDataMsg = _connector.ReadExpecting <CopyDataMessage>().Length;
            var headerLen = NpgsqlRawCopyStream.BinarySignature.Length + 4 + 4;

            _buf.Ensure(headerLen);
            if (NpgsqlRawCopyStream.BinarySignature.Any(t => _buf.ReadByte() != t))
            {
                throw new NpgsqlException("Invalid COPY binary signature at beginning!");
            }
            var flags = _buf.ReadInt32();

            if (flags != 0)
            {
                throw new NotSupportedException("Unsupported flags in COPY operation (OID inclusion?)");
            }
            _buf.ReadInt32();   // Header extensions, currently unused
            _leftToReadInDataMsg -= headerLen;
        }