Example #1
0
        void Send(PopulateMethod populateMethod)
        {
            while (true)
            {
                var directBuf = new DirectBuffer();
                var completed = populateMethod(ref directBuf);
                _connector.SendBuffer();
                if (completed)
                    break;  // Sent all messages

                // The following is an optimization hack for writing large byte arrays without passing
                // through our buffer
                if (directBuf.Buffer != null)
                {
                    _connector.WriteBuffer.DirectWrite(directBuf.Buffer, directBuf.Offset, directBuf.Size == 0 ? directBuf.Buffer.Length : directBuf.Size);
                    directBuf.Buffer = null;
                    directBuf.Size = 0;
                }

                if (_writeStatementIndex > 0)
                {
                    // We've send all the messages for the first statement in a multistatement command.
                    // If we continue blocking writes for the rest of the messages, we risk a deadlock where
                    // PostgreSQL sends large results for the first statement, while we're sending large
                    // parameter data for the second. To avoid this, switch to async sends.
                    // See #641
                    RemainingSendTask = SendRemaining(populateMethod, CancellationToken.None);
                    return;
                }
            }
        }
Example #2
0
        /// <summary>
        /// This method is used to asynchronously sends all remaining protocol messages for statements
        /// beyond the first one, and *without* waiting for the send to complete. This technique is
        /// used to avoid the deadlock described in #641 by allowing the user to read query results
        /// while at the same time sending messages for later statements.
        /// </summary>
        async Task SendRemaining(PopulateMethod populateMethod, CancellationToken cancellationToken)
        {
            Contract.Requires(_writeStatementIndex > 0);
            try
            {
                while (true)
                {
                    var directBuf = new DirectBuffer();
                    var completed = populateMethod(ref directBuf);
                    await _connector.SendBufferAsync(cancellationToken).ConfigureAwait(false);
                    if (completed)
                        return; // Sent all messages

                    // The following is an optimization hack for writing large byte arrays without passing
                    // through our buffer
                    if (directBuf.Buffer != null)
                    {
                        await _connector.WriteBuffer.DirectWriteAsync(directBuf.Buffer, directBuf.Offset,
                                directBuf.Size == 0 ? directBuf.Buffer.Length : directBuf.Size, cancellationToken
                        ).ConfigureAwait(false);
                        directBuf.Buffer = null;
                        directBuf.Size = 0;
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("Exception while asynchronously sending remaining messages", e, _connector.Id);
            }
        }
Example #3
0
 /// <summary>
 /// Populates the specified pool with the specified number of objects, so that they do not need instantiating later.
 /// </summary>
 /// <param name="poolName">The name of the pool to populate.</param>
 /// <param name="quantity">The number of objects to populate it with.</param>
 /// <param name="method">The population mode.</param>
 public void Populate(string poolName, int quantity, PopulateMethod method = PopulateMethod.Set)
 {
     GetPool(poolName).Populate(quantity, method);
 }