Permalink
Browse files

Merge branch 'hotfix/3.2.4'

  • Loading branch information...
roji committed Jun 13, 2017
2 parents 89d38c8 + 2f853e6 commit 91980555fe8730a65f3e76e7382d8b9b302da8d6
View
@@ -1,5 +1,5 @@
image: Visual Studio 2017
version: 3.2.3-{build}
version: 3.2.4-{build}
environment:
global:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
View
@@ -0,0 +1,27 @@
language: csharp
dist: trusty
sudo: false
mono: none
dotnet: 1.0.4
services:
- postgresql
addons:
postgresql: "9.6"
env:
- NPGSQL_TEST_DB: '"Host=localhost;Database=npgsql_tests;Username=npgsql_tests;Password=npgsql_tests"'
before_script:
- psql -U postgres -c "CREATE USER npgsql_tests PASSWORD 'npgsql_tests' SUPERUSER"
- psql -U postgres -c "CREATE DATABASE npgsql_tests OWNER npgsql_tests"
- psql -U postgres -c "CREATE EXTENSION postgis" npgsql_tests
- dotnet restore -v Minimal
script:
- dotnet build "test/Npgsql.Tests" -c Debug -f netcoreapp1.1
- dotnet test "test/Npgsql.Tests/Npgsql.Tests.csproj" -c Debug -f netcoreapp1.1
cache:
directories:
- $HOME/.nuget/packages
@@ -43,6 +43,8 @@ Parameter keywords are case-insensitive.
| Command Timeout | The time to wait (in seconds) while trying to execute a command before terminating the attempt and generating an error. Set to zero for infinity. | 30 |
| Internal Command Timeout | The time to wait (in seconds) while trying to execute a an internal command before terminating the attempt and generating an error. -1 uses CommandTimeout, 0 means no timeout. | -1 |
| Keepalive | The number of seconds of connection inactivity before Npgsql sends a keepalive query. | disabled |
| Tcp Keepalive Time | The number of milliseconds of connection inactivity before a TCP keepalive query is sent. Use of this option is discouraged, use KeepAlive instead if possible. Supported only on Windows. | disabled |
| Tcp Keepalive Interval | The interval, in milliseconds, between when successive keep-alive packets are sent if no acknowledgement is received. TcpKeepAliveTime must be non-zero as well. Supported only on Windows. | value of TcpKeepAliveTime |
## Performance
View
@@ -13,6 +13,8 @@ event if the keepalive fails.
Note that you should only turn this feature on if you need it. Unless you know you'll have long-lived idle connections, and that your
backend (or network equipment) will interfere with these connections, it's better to leave this off.
Note: Npgsql does not turn on TCP keepalive because that feature isn't universally reliable across all network
equipment.
## TCP Keepalives
Npgsql also supports TCP keepalive, which is different from the application-level keepalive described above. To better understand the different kinds of keepalives, see [this blog post](http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html). In a nutshell, while application-level keepalive will always work, TCP keepalive depends on your networking stack properly supporting it, etc.
One known case in which TCP keepalive may be necessary, is when you need keepalives during query processing, as opposed to between queries; this is the case if you send a query for processing, and plan to spend a lot of time before getting any response from the server (see [#1596](https://github.com/npgsql/npgsql/issues/1596) for an example). TCP keepalive may also be helpful in some other cases.
View
@@ -6,7 +6,7 @@
<Copyright>Copyright 2017 © The Npgsql Development Team</Copyright>
<Company>Npgsql</Company>
<PackageTags>npgsql postgresql postgres ado ado.net database sql</PackageTags>
<VersionPrefix>3.2.3</VersionPrefix>
<VersionPrefix>3.2.4</VersionPrefix>
<TargetFrameworks>net45;net451;netstandard1.3;netstandard2.0</TargetFrameworks>
<WarningsAsErrors>true</WarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@@ -406,8 +406,11 @@ public override void Prepare()
if (statement.IsPrepared)
continue;
statement.PreparedStatement = connector.PreparedStatementManager.GetOrAddExplicit(statement);
if (statement.PreparedStatement?.State == PreparedState.NotYetPrepared)
if (statement.PreparedStatement?.State == PreparedState.NotPrepared)
{
statement.PreparedStatement.State = PreparedState.ToBePrepared;
needToPrepare = true;
}
}
// It's possible the command was already prepared, or that presistent prepared statements were found for
@@ -722,7 +725,7 @@ async Task SendExecute(bool async, CancellationToken cancellationToken)
var statement = _statements[i];
var pStatement = statement.PreparedStatement;
if (pStatement == null || pStatement.State == PreparedState.NotYetPrepared)
if (pStatement == null || pStatement.State == PreparedState.ToBePrepared)
{
if (pStatement?.StatementBeingReplaced != null)
{
@@ -745,7 +748,7 @@ await connector.ParseMessage
bind.UnknownResultTypeList = UnknownResultTypeList;
await connector.BindMessage.Write(buf, async, cancellationToken);
if (pStatement == null || pStatement.State == PreparedState.NotYetPrepared)
if (pStatement == null || pStatement.State == PreparedState.ToBePrepared)
{
await connector.DescribeMessage
.Populate(StatementOrPortal.Portal)
@@ -826,7 +829,7 @@ async Task SendPrepare(bool async, CancellationToken cancellationToken)
// A statement may be already prepared, already in preparation (i.e. same statement twice
// in the same command), or we can't prepare (overloaded SQL)
if (pStatement?.State != PreparedState.NotYetPrepared)
if (pStatement?.State != PreparedState.ToBePrepared)
continue;
var statementToClose = pStatement.StatementBeingReplaced;
@@ -895,13 +898,13 @@ await connector.CloseMessage
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task representing the asynchronous operation, with the number of rows affected if known; -1 otherwise.</returns>
public override async Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
using (NoSynchronizationContextScope.Enter())
using (cancellationToken.Register(Cancel))
return await ExecuteNonQuery(true, cancellationToken);
}
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
=> SynchronizationContextSwitcher.NoContext(async () =>
{
cancellationToken.ThrowIfCancellationRequested();
using (cancellationToken.Register(Cancel))
return await ExecuteNonQuery(true, cancellationToken);
});
[MethodImpl(MethodImplOptions.AggressiveInlining)]
async Task<int> ExecuteNonQuery(bool async, CancellationToken cancellationToken)
@@ -936,13 +939,13 @@ async Task<int> ExecuteNonQuery(bool async, CancellationToken cancellationToken)
/// <returns>A task representing the asynchronous operation, with the first column of the
/// first row in the result set, or a null reference if the result set is empty.</returns>
[ItemCanBeNull]
public override async Task<object> ExecuteScalarAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
using (NoSynchronizationContextScope.Enter())
using (cancellationToken.Register(Cancel))
return await ExecuteScalar(true, cancellationToken);
}
public override Task<object> ExecuteScalarAsync(CancellationToken cancellationToken)
=> SynchronizationContextSwitcher.NoContext(async () =>
{
cancellationToken.ThrowIfCancellationRequested() ;
using (cancellationToken.Register(Cancel))
return await ExecuteScalar(true, cancellationToken);
});
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ItemCanBeNull]
@@ -985,13 +988,13 @@ async ValueTask<object> ExecuteScalar(bool async, CancellationToken cancellation
/// <param name="behavior">An instance of <see cref="CommandBehavior"/>.</param>
/// <param name="cancellationToken">A task representing the operation.</param>
/// <returns></returns>
protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
using (NoSynchronizationContextScope.Enter())
using (cancellationToken.Register(Cancel))
return await ExecuteDbDataReader(behavior, true, cancellationToken);
}
protected override Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
=> SynchronizationContextSwitcher.NoContext(async () =>
{
cancellationToken.ThrowIfCancellationRequested();
using (cancellationToken.Register(Cancel))
return await ExecuteDbDataReader(behavior, true, cancellationToken);
});
/// <summary>
/// Executes the command text against the connection.
@@ -1000,7 +1003,7 @@ protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBeha
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) => ExecuteDbDataReader(behavior, false, CancellationToken.None).GetAwaiter().GetResult();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
async ValueTask<NpgsqlDataReader> ExecuteDbDataReader(CommandBehavior behavior, bool async, CancellationToken cancellationToken)
async ValueTask<DbDataReader> ExecuteDbDataReader(CommandBehavior behavior, bool async, CancellationToken cancellationToken)
{
var connector = CheckReadyAndGetConnector();
connector.StartUserAction(this);
@@ -149,11 +149,8 @@ public NpgsqlConnection(string connectionString)
/// </remarks>
/// <param name="cancellationToken">The cancellation instruction.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public override async Task OpenAsync(CancellationToken cancellationToken)
{
using (NoSynchronizationContextScope.Enter())
await Open(true, cancellationToken);
}
public override Task OpenAsync(CancellationToken cancellationToken)
=> SynchronizationContextSwitcher.NoContext(async () => await Open(true, cancellationToken));
void GetPoolAndSettings()
{
@@ -882,6 +882,52 @@ public int KeepAlive
}
int _keepAlive;
/// <summary>
/// The number of seconds of connection inactivity before a TCP keepalive query is sent.
/// Use of this option is discouraged, use <see cref="KeepAlive"/> instead if possible.
/// Set to 0 (the default) to disable. Supported only on Windows.
/// </summary>
[Category("Advanced")]
[Description("The number of milliseconds of connection inactivity before a TCP keepalive query is sent.")]
[DisplayName("TCP Keepalive Time")]
[NpgsqlConnectionStringProperty]
public int TcpKeepAliveTime
{
get => _tcpKeepAliveTime;
set
{
if (value < 0)
throw new ArgumentOutOfRangeException(nameof(value), value, "TcpKeepAliveTime can't be negative");
_tcpKeepAliveTime = value;
SetValue(nameof(TcpKeepAliveTime), value);
}
}
int _tcpKeepAliveTime;
/// <summary>
/// The interval, in milliseconds, between when successive keep-alive packets are sent if no acknowledgement is received.
/// Defaults to the value of <see cref="TcpKeepAliveTime"/>. <see cref="TcpKeepAliveTime"/> must be non-zero as well.
/// Supported only on Windows.
/// </summary>
[Category("Advanced")]
[Description("The interval, in milliseconds, between when successive keep-alive packets are sent if no acknowledgement is received.")]
[DisplayName("TCP Keepalive Interval")]
[NpgsqlConnectionStringProperty]
public int TcpKeepAliveInterval
{
get => _tcpKeepAliveInterval;
set
{
if (value < 0)
throw new ArgumentOutOfRangeException(nameof(value), value, "TcpKeepAliveInterval can't be negative");
_tcpKeepAliveInterval = value;
SetValue(nameof(TcpKeepAliveInterval), value);
}
}
int _tcpKeepAliveInterval;
/// <summary>
/// Determines the size of the internal buffer Npgsql uses when reading. Increasing may improve performance if transferring large values from the database.
/// </summary>
Oops, something went wrong.

0 comments on commit 9198055

Please sign in to comment.