Use the same environment handle in connections acquired from the pool as using

a new environment handle results in strange errors in certain situations.
This commit is contained in:
Anthony Tuininga 2008-11-11 21:25:05 +00:00
parent 39333aa7d4
commit 3e6a6ef8b2
3 changed files with 85 additions and 44 deletions

View File

@ -707,7 +707,9 @@ static int Connection_Init(
} }
// set up the environment // set up the environment
self->environment = Environment_New(threaded, events); if (pool)
self->environment = Environment_Clone(pool->environment);
else self->environment = Environment_NewFromScratch(threaded, events);
if (!self->environment) if (!self->environment)
return -1; return -1;

View File

@ -13,6 +13,7 @@ typedef struct {
int maxBytesPerCharacter; int maxBytesPerCharacter;
int fixedWidth; int fixedWidth;
ub4 maxStringBytes; ub4 maxStringBytes;
int cloned;
} udt_Environment; } udt_Environment;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -63,23 +64,49 @@ static PyTypeObject g_EnvironmentType = {
// Create a new environment object. // Create a new environment object.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static udt_Environment *Environment_New( static udt_Environment *Environment_New(
OCIEnv *handle) // handle to use
{
udt_Environment *env;
sword status;
// create a new object for the Oracle environment
env = PyObject_NEW(udt_Environment, &g_EnvironmentType);
if (!env)
return NULL;
env->handle = NULL;
env->errorHandle = NULL;
env->fixedWidth = 1;
env->maxBytesPerCharacter = CXORA_BYTES_PER_CHAR;
env->maxStringBytes = MAX_STRING_CHARS * CXORA_BYTES_PER_CHAR;
env->cloned = 0;
// create the error handle
status = OCIHandleAlloc(handle, (dvoid**) &env->errorHandle,
OCI_HTYPE_ERROR, 0, 0);
if (Environment_CheckForError(env, status,
"Environment_New(): create error handle") < 0) {
Py_DECREF(env);
return NULL;
}
env->handle = handle;
return env;
}
//-----------------------------------------------------------------------------
// Environment_NewFromScratch()
// Create a new environment object from scratch.
//-----------------------------------------------------------------------------
static udt_Environment *Environment_NewFromScratch(
int threaded, // use threaded mode? int threaded, // use threaded mode?
int events) // use events mode? int events) // use events mode?
{ {
udt_Environment *environment; udt_Environment *env;
OCIEnv *handle;
sword status; sword status;
ub4 mode; ub4 mode;
// create a new object for the Oracle environment
environment = PyObject_NEW(udt_Environment, &g_EnvironmentType);
if (!environment)
return NULL;
environment->handle = NULL;
environment->errorHandle = NULL;
environment->fixedWidth = 1;
environment->maxBytesPerCharacter = CXORA_BYTES_PER_CHAR;
environment->maxStringBytes = MAX_STRING_CHARS * CXORA_BYTES_PER_CHAR;
// turn threading mode on, if desired // turn threading mode on, if desired
mode = OCI_OBJECT; mode = OCI_OBJECT;
if (threaded) if (threaded)
@ -89,56 +116,66 @@ static udt_Environment *Environment_New(
mode |= OCI_EVENTS; mode |= OCI_EVENTS;
#endif #endif
// create the environment handle // create the new environment handle
status = OCIEnvNlsCreate(&environment->handle, mode, NULL, NULL, NULL, status = OCIEnvNlsCreate(&handle, mode, NULL, NULL, NULL,
NULL, 0, NULL, CXORA_CHARSETID, CXORA_CHARSETID); NULL, 0, NULL, CXORA_CHARSETID, CXORA_CHARSETID);
if (!environment->handle) { if (!handle ||
Py_DECREF(environment); (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO)) {
PyErr_SetString(g_InterfaceErrorException, PyErr_SetString(g_InterfaceErrorException,
"Unable to acquire Oracle environment handle"); "Unable to acquire Oracle environment handle");
return NULL; return NULL;
} }
if (Environment_CheckForError(environment, status,
"Environment_New(): create env handle") < 0) {
environment->handle = NULL;
Py_DECREF(environment);
return NULL;
}
// create the error handle // create the environment object
status = OCIHandleAlloc(environment->handle, env = Environment_New(handle);
(dvoid**) &environment->errorHandle, OCI_HTYPE_ERROR, 0, 0); if (!env) {
if (Environment_CheckForError(environment, status, OCIHandleFree(handle, OCI_HTYPE_ENV);
"Environment_New(): create error handle") < 0) {
Py_DECREF(environment);
return NULL; return NULL;
} }
#ifndef WITH_UNICODE #ifndef WITH_UNICODE
// acquire max bytes per character // acquire max bytes per character
status = OCINlsNumericInfoGet(environment->handle, status = OCINlsNumericInfoGet(env->handle, env->errorHandle,
environment->errorHandle, &environment->maxBytesPerCharacter, &env->maxBytesPerCharacter, OCI_NLS_CHARSET_MAXBYTESZ);
OCI_NLS_CHARSET_MAXBYTESZ); if (Environment_CheckForError(env, status,
if (Environment_CheckForError(environment, status,
"Environment_New(): get max bytes per character") < 0) { "Environment_New(): get max bytes per character") < 0) {
Py_DECREF(environment); Py_DECREF(env);
return NULL; return NULL;
} }
environment->maxStringBytes = env->maxStringBytes = MAX_STRING_CHARS * env->maxBytesPerCharacter;
MAX_STRING_CHARS * environment->maxBytesPerCharacter;
// acquire whether character set is fixed width // acquire whether character set is fixed width
status = OCINlsNumericInfoGet(environment->handle, status = OCINlsNumericInfoGet(env->handle, env->errorHandle,
environment->errorHandle, &environment->fixedWidth, &env->fixedWidth, OCI_NLS_CHARSET_FIXEDWIDTH);
OCI_NLS_CHARSET_FIXEDWIDTH); if (Environment_CheckForError(env, status,
if (Environment_CheckForError(environment, status, "Environment_New(): determine if charset fixed width") < 0) {
"Environment_New(): determine if charset is fixed width") < 0) { Py_DECREF(env);
Py_DECREF(environment);
return NULL; return NULL;
} }
#endif #endif
return environment; return env;
}
//-----------------------------------------------------------------------------
// Environment_Clone()
// Clone an existing environment which is used when acquiring a connection
// from a session pool, for example.
//-----------------------------------------------------------------------------
static udt_Environment *Environment_Clone(
udt_Environment *cloneEnv) // environment to clone
{
udt_Environment *env;
env = Environment_New(cloneEnv->handle);
if (!env)
return NULL;
env->maxBytesPerCharacter = cloneEnv->maxBytesPerCharacter;
env->maxStringBytes = cloneEnv->maxStringBytes;
env->fixedWidth = cloneEnv->fixedWidth;
env->cloned = 1;
return env;
} }
@ -150,7 +187,9 @@ static udt_Environment *Environment_New(
static void Environment_Free( static void Environment_Free(
udt_Environment *environment) // environment object udt_Environment *environment) // environment object
{ {
if (environment->handle) if (environment->errorHandle)
OCIHandleFree(environment->errorHandle, OCI_HTYPE_ERROR);
if (environment->handle && !environment->cloned)
OCIHandleFree(environment->handle, OCI_HTYPE_ENV); OCIHandleFree(environment->handle, OCI_HTYPE_ENV);
PyObject_DEL(environment); PyObject_DEL(environment);
} }

View File

@ -235,7 +235,7 @@ static int SessionPool_Init(
self->homogeneous = homogeneous; self->homogeneous = homogeneous;
// set up the environment // set up the environment
self->environment = Environment_New(threaded, events); self->environment = Environment_NewFromScratch(threaded, events);
if (!self->environment) if (!self->environment)
return -1; return -1;