From b9381892a5da18bd1afeb13f9bb24987c2b5ea36 Mon Sep 17 00:00:00 2001 From: Anthony Tuininga Date: Wed, 16 May 2018 14:09:59 -0600 Subject: [PATCH] Added support for timed waits when acquiring a session from a session pool and added support for specifying the timeout and maximum lifetime session of sessions in the pool when the pool is being created. --- doc/src/module.rst | 28 +++++++++++++++++++++++++++- src/cxoModule.c | 2 ++ src/cxoSessionPool.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/doc/src/module.rst b/doc/src/module.rst index d94a059..85f2be5 100644 --- a/doc/src/module.rst +++ b/doc/src/module.rst @@ -180,7 +180,7 @@ Module Interface increment=1, connectiontype=cx_Oracle.Connection, threaded=False, \ getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT, events=False, \ homogeneous=True, externalauth=False, encoding=None, nencoding=None, \ - edition=None) + edition=None, timeout=0, waitTimeout=0, maxLifetimeSession=0) Create and return a :ref:`session pool object `. This allows for very fast connections to the database and is of primary use in a @@ -216,6 +216,26 @@ Module Interface the edition to use for the sessions in the pool. It is only relevant if both the client and the server are at least Oracle Database 11.2. + The timeout parameter is expected to be an integer, if specified, and sets + the length of time (in seconds) after which idle sessions in the pool are + terminated. Note that termination only occurs when another session is + released back to the pool. The default value of 0 means that no idle + are terminated. + + The waitTimeout parameter is expected to be an integer, if specified, and + sets the length of time (in milliseconds) that the caller should wait for + a session to become available in the pool before returning with an error. + This value is only used if the getmode parameter is set to the value + :data:`cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT`. + + The maxLifetimeSession parameter is expected to be an integer, if + specified, and sets the length of time (in seconds) a session may remain + in the pool. Sessions in the pool are terminated after they have been in + the pool for the specified period of time. Note that termination only + occurs when another session is released back to the pool. The default value + is 0 which means that there is no maximum length of time that a session may + exist in the pool. + .. note:: This method is an extension to the DB API definition. @@ -753,6 +773,12 @@ values for the getmode parameter of the :meth:`SessionPool()` method. session is available if there are no free sessions available in the pool. +.. data:: SPOOL_ATTRVAL_TIMEDWAIT + + This constant is used to specify that the caller should wait for a period + of time (defined by the waitTimeout parameter) for a session to become + available before returning with an error. + Session Pool Purity ------------------- diff --git a/src/cxoModule.c b/src/cxoModule.c index f236666..80c9f5c 100644 --- a/src/cxoModule.c +++ b/src/cxoModule.c @@ -407,6 +407,8 @@ static PyObject *cxoModule_initialize(void) CXO_ADD_INT_CONSTANT("SPOOL_ATTRVAL_WAIT", DPI_MODE_POOL_GET_WAIT) CXO_ADD_INT_CONSTANT("SPOOL_ATTRVAL_NOWAIT", DPI_MODE_POOL_GET_NOWAIT) CXO_ADD_INT_CONSTANT("SPOOL_ATTRVAL_FORCEGET", DPI_MODE_POOL_GET_FORCEGET) + CXO_ADD_INT_CONSTANT("SPOOL_ATTRVAL_TIMEDWAIT", + DPI_MODE_POOL_GET_TIMEDWAIT) // add constants for database shutdown modes CXO_ADD_INT_CONSTANT("DBSHUTDOWN_ABORT", DPI_MODE_SHUTDOWN_ABORT) diff --git a/src/cxoSessionPool.c b/src/cxoSessionPool.c index 1d7c3a3..8f87493 100644 --- a/src/cxoSessionPool.c +++ b/src/cxoSessionPool.c @@ -29,11 +29,13 @@ static PyObject *cxoSessionPool_getMaxLifetimeSession(cxoSessionPool*, void*); static PyObject *cxoSessionPool_getOpenCount(cxoSessionPool*, void*); static PyObject *cxoSessionPool_getStmtCacheSize(cxoSessionPool*, void*); static PyObject *cxoSessionPool_getTimeout(cxoSessionPool*, void*); +static PyObject *cxoSessionPool_getWaitTimeout(cxoSessionPool*, void*); static int cxoSessionPool_setGetMode(cxoSessionPool*, PyObject*, void*); static int cxoSessionPool_setMaxLifetimeSession(cxoSessionPool*, PyObject*, void*); static int cxoSessionPool_setStmtCacheSize(cxoSessionPool*, PyObject*, void*); static int cxoSessionPool_setTimeout(cxoSessionPool*, PyObject*, void*); +static int cxoSessionPool_setWaitTimeout(cxoSessionPool*, PyObject*, void*); //----------------------------------------------------------------------------- @@ -80,6 +82,8 @@ static PyGetSetDef cxoSessionPoolCalcMembers[] = { (setter) cxoSessionPool_setMaxLifetimeSession, 0, 0 }, { "stmtcachesize", (getter) cxoSessionPool_getStmtCacheSize, (setter) cxoSessionPool_setStmtCacheSize, 0, 0 }, + { "wait_timeout", (getter) cxoSessionPool_getWaitTimeout, + (setter) cxoSessionPool_setWaitTimeout, 0, 0 }, { NULL } }; @@ -166,7 +170,7 @@ static int cxoSessionPool_init(cxoSessionPool *pool, PyObject *args, static char *keywordList[] = { "user", "password", "dsn", "min", "max", "increment", "connectiontype", "threaded", "getmode", "events", "homogeneous", "externalauth", "encoding", "nencoding", "edition", - NULL }; + "timeout", "waitTimeout", "maxLifetimeSession", NULL }; // parse arguments and keywords usernameObj = passwordObj = dsnObj = editionObj = Py_None; @@ -185,12 +189,13 @@ static int cxoSessionPool_init(cxoSessionPool *pool, PyObject *args, (uint32_t) strlen(dpiCommonParams.driverName); if (dpiContext_initPoolCreateParams(cxoDpiContext, &dpiCreateParams) < 0) return cxoError_raiseAndReturnInt(); - if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|OOOiiiOObOOOssO", + if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|OOOiiiOObOOOssOiii", keywordList, &usernameObj, &passwordObj, &dsnObj, &minSessions, &maxSessions, &sessionIncrement, &connectionType, &threadedObj, &dpiCreateParams.getMode, &eventsObj, &homogeneousObj, &externalAuthObj, &dpiCommonParams.encoding, - &dpiCommonParams.nencoding, &editionObj)) + &dpiCommonParams.nencoding, &editionObj, &dpiCreateParams.timeout, + &dpiCreateParams.waitTimeout, &dpiCreateParams.maxLifetimeSession)) return -1; if (!PyType_Check(connectionType)) { cxoError_raiseFromString(cxoProgrammingErrorException, @@ -529,6 +534,17 @@ static PyObject *cxoSessionPool_getTimeout(cxoSessionPool *pool, void *unused) } +//----------------------------------------------------------------------------- +// cxoSessionPool_getWaitTimeout() +// Return the wait timeout for connections in the session pool. +//----------------------------------------------------------------------------- +static PyObject *cxoSessionPool_getWaitTimeout(cxoSessionPool *pool, + void *unused) +{ + return cxoSessionPool_getAttribute(pool, dpiPool_getWaitTimeout); +} + + //----------------------------------------------------------------------------- // cxoSessionPool_setGetMode() // Set the "get" mode for connections in the session pool. @@ -582,3 +598,14 @@ static int cxoSessionPool_setTimeout(cxoSessionPool *pool, PyObject *value, return cxoSessionPool_setAttribute(pool, value, dpiPool_setTimeout); } + +//----------------------------------------------------------------------------- +// cxoSessionPool_setWaitTimeout() +// Set the wait timeout for connections in the session pool. +//----------------------------------------------------------------------------- +static int cxoSessionPool_setWaitTimeout(cxoSessionPool *pool, PyObject *value, + void *unused) +{ + return cxoSessionPool_setAttribute(pool, value, dpiPool_setWaitTimeout); +} +