Skip to content
Permalink
Browse files

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.
  • Loading branch information
m-kuhn committed Aug 8, 2018
1 parent 71f9910 commit 7c8c6ca0984649bfbb92645948c5ce63c384c0c6
@@ -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:
@@ -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
@@ -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"
@@ -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 )
@@ -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

0 comments on commit 7c8c6ca

Please sign in to comment.
You can’t perform that action at this time.