Allow specifying the number of required connections

for a request. Most requests should reserve more
than a single connection (default: 3) and only
requests that are executed as nested expressions
should specify 1.
This commit is contained in:
Matthias Kuhn 2018-08-02 13:32:43 +02:00
parent 7033b54483
commit 14643ad98d
No known key found for this signature in database
GPG Key ID: A0E766808764D73F
5 changed files with 90 additions and 7 deletions

View File

@ -657,6 +657,40 @@ at this moment. A negative value (which is set by default) will wait forever.
Only works if the provider supports this option.
.. versionadded:: 3.0
%End
int freeConnectionsRequirement() const;
%Docstring
The amount of free connections required to start this request.
The system will block the request until the specified amount of connections
is available for usage.
By default this amount is 3. This makes sure, that we have 2 spare connections
that might be used by "nested" requests which are executed while iterating
over the results of this request.
This number should be changed to one, when we know that no nested requests happen
and that this request might happen in a nested way. This is for example given for
expression functions that do internal requests.
.. versionadded:: 3.4
%End
void setFreeConnectionsRequirement( int freeConnectionsRequirement );
%Docstring
The amount of free connections required to start this request.
The system will block the request until the specified amount of connections
is available for usage.
By default this amount is 3. This makes sure, that we have 2 spare connections
that might be used by "nested" requests which are executed while iterating
over the results of this request.
This number should be changed to one, when we know that no nested requests happen
and that this request might happen in a nested way. This is for example given for
expression functions that do internal requests.
.. versionadded:: 3.4
%End
protected:

View File

@ -29,7 +29,7 @@
#include <QThread>
#define CONN_POOL_MAX_CONCURRENT_CONNS 4
#define CONN_POOL_MAX_CONCURRENT_CONNS 6
#define CONN_POOL_EXPIRATION_TIME 60 // in seconds
@ -93,12 +93,12 @@ class QgsConnectionPoolGroup
*
* \returns initialized connection or nullptr if unsuccessful
*/
T acquire( int timeout )
T acquire( int timeout, int freeConnectionRequirement )
{
// we are going to acquire a resource - if no resource is available, we will block here
if ( timeout >= 0 )
{
if ( !sem.tryAcquire( 1, timeout ) )
if ( !sem.tryAcquire( freeConnectionRequirement, timeout ) )
return nullptr;
}
else
@ -107,8 +107,9 @@ class QgsConnectionPoolGroup
// tryAcquire is broken on Qt > 5.8 with negative timeouts - see
// https://bugreports.qt.io/browse/QTBUG-64413
// https://lists.osgeo.org/pipermail/qgis-developer/2017-November/050456.html
sem.acquire( 1 );
sem.acquire( freeConnectionRequirement );
}
sem.release( freeConnectionRequirement - 1 );
// quick (preferred) way - use cached connection
{
@ -283,9 +284,11 @@ class QgsConnectionPool
* If \a timeout is a negative value the calling thread will be blocked
* until a connection becomes available. This is the default behavior.
*
*
*
* \returns initialized connection or nullptr if unsuccessful
*/
T acquireConnection( const QString &connInfo, int timeout = -1 )
T acquireConnection( const QString &connInfo, int timeout = -1, int freeConnectionRequirement = 3 )
{
mMutex.lock();
typename T_Groups::iterator it = mGroups.find( connInfo );
@ -296,7 +299,7 @@ class QgsConnectionPool
T_Group *group = *it;
mMutex.unlock();
return group->acquire( timeout );
return group->acquire( timeout, freeConnectionRequirement );
}
//! Release an existing connection so it will get back into the pool and can be reused

View File

@ -86,6 +86,7 @@ QgsFeatureRequest &QgsFeatureRequest::operator=( const QgsFeatureRequest &rh )
mCrs = rh.mCrs;
mTransformErrorCallback = rh.mTransformErrorCallback;
mConnectionTimeout = rh.mConnectionTimeout;
mFreeConnectionsRequirement = rh.mFreeConnectionsRequirement;
return *this;
}
@ -298,6 +299,16 @@ void QgsFeatureRequest::setConnectionTimeout( int connectionTimeout )
mConnectionTimeout = connectionTimeout;
}
int QgsFeatureRequest::freeConnectionsRequirement() const
{
return mFreeConnectionsRequirement;
}
void QgsFeatureRequest::setFreeConnectionsRequirement( int freeConnectionsRequirement )
{
mFreeConnectionsRequirement = freeConnectionsRequirement;
}
#include "qgsfeatureiterator.h"
#include "qgslogger.h"

View File

@ -636,6 +636,40 @@ class CORE_EXPORT QgsFeatureRequest
*/
void setConnectionTimeout( int connectionTimeout );
/**
* The amount of free connections required to start this request.
* The system will block the request until the specified amount of connections
* is available for usage.
*
* By default this amount is 3. This makes sure, that we have 2 spare connections
* that might be used by "nested" requests which are executed while iterating
* over the results of this request.
*
* This number should be changed to one, when we know that no nested requests happen
* and that this request might happen in a nested way. This is for example given for
* expression functions that do internal requests.
*
* \since QGIS 3.4
*/
int freeConnectionsRequirement() const;
/**
* The amount of free connections required to start this request.
* The system will block the request until the specified amount of connections
* is available for usage.
*
* By default this amount is 3. This makes sure, that we have 2 spare connections
* that might be used by "nested" requests which are executed while iterating
* over the results of this request.
*
* This number should be changed to one, when we know that no nested requests happen
* and that this request might happen in a nested way. This is for example given for
* expression functions that do internal requests.
*
* \since QGIS 3.4
*/
void setFreeConnectionsRequirement( int freeConnectionsRequirement );
protected:
FilterType mFilter = FilterNone;
QgsRectangle mFilterRect;
@ -654,6 +688,7 @@ class CORE_EXPORT QgsFeatureRequest
QgsCoordinateReferenceSystem mCrs;
QgsCoordinateTransformContext mTransformContext;
int mConnectionTimeout = -1;
int mFreeConnectionsRequirement = 3;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureRequest::Flags )

View File

@ -38,7 +38,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
if ( !source->mTransactionConnection )
{
mConn = QgsPostgresConnPool::instance()->acquireConnection( mSource->mConnInfo );
mConn = QgsPostgresConnPool::instance()->acquireConnection( mSource->mConnInfo, request.connectionTimeout(), request.freeConnectionsRequirement() );
mIsTransactionConnection = false;
}
else