8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 17:23:03 +01:00

Reset external connection before put it into pool.

Update the documentation.
This commit is contained in:
hvlad 2018-05-27 12:24:47 +03:00
parent 2930edb9c0
commit d681f5288f
7 changed files with 63 additions and 20 deletions

View File

@ -9,10 +9,13 @@ Author:
Vlad Khorsun <hvlad@users.sourceforge.net>
How pool works:
- every external connection is assotiated with a pool when created
- pool maintains two lists : idle connections and active connections
- when some connection gets unused (i.e. it have no active requests and
active transactions), it puts into idle list
- every external connection is associated with a pool when created
- pool maintains two lists: idle connections and active connections
- when some connection become unused (i.e. it have no active requests and no
active transactions), it is resetted and placed into idle list (on successful
reset) or closed (if reset failed).
Connection is resetted using ALTER SESSION RESET statement. It is considered
successful if no error occurs.
- if the pool has reached max. size, the oldest idle connection is closed
- when engine ask to create a new external connection, the pool first looks
for candidate at the idle list. The search is based on 4 parameters:
@ -26,7 +29,7 @@ How pool works:
(the error is not reported to the user)
- found (and alive) connection is moved from idle list to active list and
returned to the caller
- if there are several suitable connections, the most recently used is choosed
- if there are several suitable connections, the most recently used is chosen
- if there is no suitable connection, the new one is created (and put into
active list)
- when idle connection gets expired (exceeded the lifetime), it is deleted from
@ -41,16 +44,16 @@ Key characteristics:
process
Pool parameters:
- connection life time : the time interval from the moment of the last usage of
- connection life time: the time interval from the moment of the last usage of
connection after which it will be forcibly closed
- pool size : the maximum allowed number of idle connections in the pool
- pool size: the maximum allowed number of idle connections in the pool
Pool management:
New SQL statement is introduced to manage the pool :
New SQL statement is introduced to manage the pool:
ALTER EXTERNAL CONNECTIONS POOL.
When prepared it desribed as DDL statement but have immediate effect: i.e.
When prepared it is described as DDL statement but have immediate effect: i.e.
it is executed immediately and completely, not waiting for transaction commit.
Changes applied to the in-memory instance of the pool in current Firebird
process. Therefore change in one Classic process doesn't affect other Classic
@ -72,12 +75,12 @@ The full syntax is:
where <time_part> is SECOND | MINUTE | HOUR
Set idle connection lifetime, in seconds.
Valid valus are from 1 SECOND to 24 HOUR.
Valid values are from 1 SECOND to 24 HOUR.
Default value is set in firebird.conf (see below).
- ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL
Closes all idle connections.
Disassotiates all active connections off the pool (such connections will be
Disassociates all active connections off the pool (such connections will be
closed immediately when gets unused).
- ALTER EXTERNAL CONNECTIONS POOL CLEAR OLDEST
@ -88,7 +91,7 @@ variables in 'SYSTEM' namespace:
- EXT_CONN_POOL_SIZE pool size
- EXT_CONN_POOL_LIFETIME idle connection lifetime, in seconds
- EXT_CONN_POOL_IDLE_COUNT count of currently inactive connections
- EXT_CONN_POOL_ACTIVE_COUNT count of active connections, assotiated with pool
- EXT_CONN_POOL_ACTIVE_COUNT count of active connections, associated with pool
Firebird configuration (firebird.conf) got two new settings related with pool:

View File

@ -445,10 +445,18 @@ void Provider::releaseConnection(thread_db* tdbb, Connection& conn, bool inPool)
m_connections.add(AttToConn(NULL, &conn));
}
if (!inPool || !connPool || !conn.isConnected())
if (!inPool || !connPool || !conn.isConnected() || !conn.resetSession())
{
if (connPool)
{
{
MutexLockGuard guard(m_mutex, FB_FUNCTION);
AttToConnMap::Accessor acc(&m_connections);
if (acc.locate(AttToConn(NULL, &conn)))
acc.fastRemove();
}
connPool->delConnection(tdbb, &conn, false);
}
Connection::deleteConnection(tdbb, &conn);
}

View File

@ -420,6 +420,7 @@ public:
virtual void detach(Jrd::thread_db* tdbb);
virtual bool cancelExecution(bool forced) = 0;
virtual bool resetSession() = 0;
int getSqlDialect() const { return m_sqlDialect; }

View File

@ -239,6 +239,20 @@ bool InternalConnection::cancelExecution(bool /*forced*/)
return !(status->getState() & IStatus::STATE_ERRORS);
}
bool InternalConnection::resetSession()
{
fb_assert(!m_isCurrent);
if (m_isCurrent)
return true;
FbLocalStatus status;
m_attachment->execute(&status, NULL, 0, "ALTER SESSION RESET",
m_sqlDialect, NULL, NULL, NULL, NULL);
return !(status->getState() & IStatus::STATE_ERRORS);
}
// this internal connection instance is available for the current execution context if it
// a) is current connection and current thread's attachment is equal to
// this attachment, or

View File

@ -67,6 +67,7 @@ public:
virtual void attach(Jrd::thread_db* tdbb);
virtual bool cancelExecution(bool forced);
virtual bool resetSession();
virtual bool isAvailable(Jrd::thread_db* tdbb, TraScope traScope) const;

View File

@ -239,6 +239,21 @@ bool IscConnection::cancelExecution(bool forced)
return !(status->getState() & IStatus::STATE_ERRORS);
}
bool IscConnection::resetSession()
{
if (!m_handle)
return false;
FbLocalStatus status;
m_iscProvider.isc_dsql_execute_immediate(&status, &m_handle,
NULL, 0, "ALTER SESSION RESET", m_sqlDialect, NULL);
if (!(status->getState() & IStatus::STATE_ERRORS))
return true;
return false; // (status->getErrors()[1] == isc_dsql_error);
}
// this ISC connection instance is available for the current execution context if it
// a) has no active statements or supports many active statements
// and
@ -1111,14 +1126,14 @@ ISC_STATUS ISC_EXPORT IscProvider::isc_dsql_execute2(FbStatusVector* user_status
}
ISC_STATUS ISC_EXPORT IscProvider::isc_dsql_execute_immediate(FbStatusVector* user_status,
isc_db_handle *,
isc_tr_handle *,
unsigned short,
const char*,
unsigned short,
const XSQLDA *)
isc_db_handle* db_handle, isc_tr_handle* tra_handle, unsigned short length,
const char* str, unsigned short dialect, const XSQLDA* sqlda)
{
return notImplemented(user_status);
if (!m_api.isc_dsql_execute_immediate)
return notImplemented(user_status);
return (*m_api.isc_dsql_execute_immediate) (IscStatus(user_status),
db_handle, tra_handle, length, str, dialect, sqlda);
}
ISC_STATUS ISC_EXPORT IscProvider::isc_dsql_fetch(FbStatusVector* user_status,

View File

@ -519,6 +519,7 @@ public:
virtual void attach(Jrd::thread_db* tdbb);
virtual bool cancelExecution(bool forced);
virtual bool resetSession();
virtual bool isAvailable(Jrd::thread_db* tdbb, TraScope traScope) const;
virtual bool isConnected() const { return (m_handle != 0); }