Skip to content

Commit

Permalink
Corrected internal handling of client version information when creating
Browse files Browse the repository at this point in the history
multiple contexts (#156).
  • Loading branch information
anthony-tuininga committed Apr 14, 2021
1 parent b911d86 commit 09da006
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 27 deletions.
3 changes: 3 additions & 0 deletions doc/src/releasenotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ Version 4.2 (TBD)
:func:`dpiJson_setValue()` that were made in between or to take into
account the passing of different flags (`issue 154
<https://github.com/oracle/odpi/issues/154>`__).
#) Corrected internal handling of client version information when creating
multiple contexts (`issue 156
<https://github.com/oracle/odpi/issues/156>`__).
#) Improved test suite.


Expand Down
10 changes: 6 additions & 4 deletions src/dpiGlobal.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static void *dpiGlobalEnvHandle = NULL;
static void *dpiGlobalErrorHandle = NULL;
static void *dpiGlobalThreadKey = NULL;
static dpiErrorBuffer dpiGlobalErrorBuffer;
static dpiVersionInfo dpiGlobalClientVersionInfo;
static int dpiGlobalInitialized = 0;

// a global mutex is used to ensure that only one thread is used to perform
Expand All @@ -54,7 +55,7 @@ static dpiMutexType dpiGlobalMutex;

// forward declarations of internal functions only used in this file
static int dpiGlobal__extendedInitialize(dpiContextCreateParams *params,
dpiVersionInfo **clientVersionInfo, dpiError *error);
dpiError *error);
static void dpiGlobal__finalize(void);
static int dpiGlobal__getErrorBuffer(const char *fnName, dpiError *error);

Expand Down Expand Up @@ -82,12 +83,13 @@ int dpiGlobal__ensureInitialized(const char *fnName,
if (!dpiGlobalInitialized) {
dpiMutex__acquire(dpiGlobalMutex);
if (!dpiGlobalInitialized)
dpiGlobal__extendedInitialize(params, clientVersionInfo, error);
dpiGlobal__extendedInitialize(params, error);
dpiMutex__release(dpiGlobalMutex);
if (!dpiGlobalInitialized)
return DPI_FAILURE;
}

*clientVersionInfo = &dpiGlobalClientVersionInfo;
return dpiGlobal__getErrorBuffer(fnName, error);
}

Expand All @@ -100,12 +102,12 @@ int dpiGlobal__ensureInitialized(const char *fnName,
// IANA or Oracle character set name.
//-----------------------------------------------------------------------------
static int dpiGlobal__extendedInitialize(dpiContextCreateParams *params,
dpiVersionInfo **clientVersionInfo, dpiError *error)
dpiError *error)
{
int status;

// load OCI library
if (dpiOci__loadLib(params, clientVersionInfo, error) < 0)
if (dpiOci__loadLib(params, &dpiGlobalClientVersionInfo, error) < 0)
return DPI_FAILURE;

// create threaded OCI environment for storing error buffers and for
Expand Down
2 changes: 1 addition & 1 deletion src/dpiImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1880,7 +1880,7 @@ int dpiOci__jsonDomDocGet(dpiJson *json, dpiJznDomDoc **domDoc,
int dpiOci__jsonTextBufferParse(dpiJson *json, const char *value,
uint64_t valueLength, dpiError *error);
int dpiOci__loadLib(dpiContextCreateParams *params,
dpiVersionInfo **clientVersionInfo, dpiError *error);
dpiVersionInfo *clientVersionInfo, dpiError *error);
int dpiOci__lobClose(dpiLob *lob, dpiError *error);
int dpiOci__lobCreateTemporary(dpiLob *lob, dpiError *error);
int dpiOci__lobFileExists(dpiLob *lob, int *exists, dpiError *error);
Expand Down
42 changes: 20 additions & 22 deletions src/dpiOci.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ typedef struct {
// forward declarations of internal functions only used in this file
static void *dpiOci__allocateMem(void *unused, size_t size);
static void dpiOci__freeMem(void *unused, void *ptr);
static int dpiOci__loadLibValidate(dpiError *error);
static int dpiOci__loadLibValidate(dpiVersionInfo *versionInfo,
dpiError *error);
static int dpiOci__loadLibWithDir(dpiOciLoadLibParams *loadParams,
const char *dirName, size_t dirNameLength, int scanAllNames,
dpiError *error);
Expand Down Expand Up @@ -480,9 +481,6 @@ static const char *dpiOciLibNames[] = {
NULL
};

// version information for loaded OCI library
static dpiVersionInfo dpiOciLibVersionInfo;

// all OCI symbols used by ODPI-C
static struct {
dpiOciFnType__aqDeq fnAqDeq;
Expand Down Expand Up @@ -2004,7 +2002,7 @@ static int dpiOci__loadLibWithDir(dpiOciLoadLibParams *loadParams,
// Load the OCI library.
//-----------------------------------------------------------------------------
int dpiOci__loadLib(dpiContextCreateParams *params,
dpiVersionInfo **clientVersionInfo, dpiError *error)
dpiVersionInfo *clientVersionInfo, dpiError *error)
{
static const char *envNamesToCheck[] = {
"ORACLE_HOME",
Expand Down Expand Up @@ -2128,7 +2126,7 @@ int dpiOci__loadLib(dpiContextCreateParams *params,

// validate library
dpiOciLibHandle = loadLibParams.handle;
if (dpiOci__loadLibValidate(error) < 0) {
if (dpiOci__loadLibValidate(clientVersionInfo, error) < 0) {
#ifdef _WIN32
FreeLibrary(dpiOciLibHandle);
#else
Expand All @@ -2139,7 +2137,6 @@ int dpiOci__loadLib(dpiContextCreateParams *params,
return DPI_FAILURE;
}

*clientVersionInfo = &dpiOciLibVersionInfo;
return DPI_SUCCESS;
}

Expand All @@ -2148,7 +2145,8 @@ int dpiOci__loadLib(dpiContextCreateParams *params,
// dpiOci__loadLibValidate() [INTERNAL]
// Validate the OCI library after loading.
//-----------------------------------------------------------------------------
static int dpiOci__loadLibValidate(dpiError *error)
static int dpiOci__loadLibValidate(dpiVersionInfo *clientVersionInfo,
dpiError *error)
{
if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB)
dpiDebug__print("validating loaded library\n");
Expand All @@ -2158,24 +2156,24 @@ static int dpiOci__loadLibValidate(dpiError *error)
(void**) &dpiOciSymbols.fnClientVersion, NULL) < 0)
return dpiError__set(error, "load symbol OCIClientVersion",
DPI_ERR_ORACLE_CLIENT_UNSUPPORTED);
memset(&dpiOciLibVersionInfo, 0, sizeof(dpiOciLibVersionInfo));
(*dpiOciSymbols.fnClientVersion)(&dpiOciLibVersionInfo.versionNum,
&dpiOciLibVersionInfo.releaseNum,
&dpiOciLibVersionInfo.updateNum,
&dpiOciLibVersionInfo.portReleaseNum,
&dpiOciLibVersionInfo.portUpdateNum);
if (dpiOciLibVersionInfo.versionNum == 0)
memset(clientVersionInfo, 0, sizeof(*clientVersionInfo));
(*dpiOciSymbols.fnClientVersion)(&clientVersionInfo->versionNum,
&clientVersionInfo->releaseNum,
&clientVersionInfo->updateNum,
&clientVersionInfo->portReleaseNum,
&clientVersionInfo->portUpdateNum);
if (clientVersionInfo->versionNum == 0)
return dpiError__set(error, "get OCI client version",
DPI_ERR_ORACLE_CLIENT_UNSUPPORTED);
dpiOciLibVersionInfo.fullVersionNum = (uint32_t)
DPI_ORACLE_VERSION_TO_NUMBER(dpiOciLibVersionInfo.versionNum,
dpiOciLibVersionInfo.releaseNum,
dpiOciLibVersionInfo.updateNum,
dpiOciLibVersionInfo.portReleaseNum,
dpiOciLibVersionInfo.portUpdateNum);
clientVersionInfo->fullVersionNum = (uint32_t)
DPI_ORACLE_VERSION_TO_NUMBER(clientVersionInfo->versionNum,
clientVersionInfo->releaseNum,
clientVersionInfo->updateNum,
clientVersionInfo->portReleaseNum,
clientVersionInfo->portUpdateNum);

// OCI version must be a minimum of 11.2
if (dpiUtils__checkClientVersion(&dpiOciLibVersionInfo, 11, 2, error) < 0)
if (dpiUtils__checkClientVersion(clientVersionInfo, 11, 2, error) < 0)
return DPI_FAILURE;

// initialize threading capability in the OCI library
Expand Down
49 changes: 49 additions & 0 deletions test/TestContext.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,53 @@ int dpiTest_106_validCtxParams(dpiTestCase *testCase, dpiTestParams *params)
}


//-----------------------------------------------------------------------------
// dpiTest_107_multipleContexts()
// Verify that dpiContext_createWithParams() can be called twice and the same // version information is provided in both cases.
//-----------------------------------------------------------------------------
int dpiTest_107_multipleContexts(dpiTestCase *testCase, dpiTestParams *params)
{
dpiVersionInfo versionInfo1, versionInfo2;
dpiContext *context1, *context2;
dpiErrorInfo errorInfo;

// create first context
if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
NULL, &context1, &errorInfo) < 0)
return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo);
if (dpiContext_getClientVersion(context1, &versionInfo1) < 0) {
dpiContext_getError(context1, &errorInfo);
return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo);
}

// create second context
if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
NULL, &context2, &errorInfo) < 0)
return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo);
if (dpiContext_getClientVersion(context2, &versionInfo2) < 0) {
dpiContext_getError(context2, &errorInfo);
return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo);
}

// verify version information is the same
if (dpiTestCase_expectUintEqual(testCase, versionInfo1.versionNum,
versionInfo2.versionNum) < 0)
return DPI_FAILURE;

// cleanup
if (dpiContext_destroy(context1) < 0) {
dpiContext_getError(context1, &errorInfo);
return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo);
}
if (dpiContext_destroy(context2) < 0) {
dpiContext_getError(context2, &errorInfo);
return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo);
}

return DPI_SUCCESS;
}


//-----------------------------------------------------------------------------
// main()
//-----------------------------------------------------------------------------
Expand All @@ -161,5 +208,7 @@ int main(int argc, char **argv)
"dpiContext_destroy() called twice on same pointer");
dpiTestSuite_addCase(dpiTest_106_validCtxParams,
"dpiContext_createWithParams() with creation parameters");
dpiTestSuite_addCase(dpiTest_107_multipleContexts,
"dpiContext_createWithParams() twice");
return dpiTestSuite_run();
}

0 comments on commit 09da006

Please sign in to comment.