Home » Developer & Programmer » Precompilers, OCI & OCCI » Problems with OCI without an environment (ORACLE_HOME not set)
Problems with OCI without an environment (ORACLE_HOME not set) [message #178506] Wed, 21 June 2006 05:17 Go to next message
adamb
Messages: 6
Registered: April 2006
Location: London, UK
Junior Member
System: Solaris 9, Sun-Fire-V440

Our application has Oracle 9i as one of the possible persistence backends. Oracle is not always available at all clients sites so we use dlopen/dlsym to access the required OCI functions in clntsh on demand. Moreover, the app is started by inetd, so there is no environment and ORACLE_HOME is not set. The result is that OCIEnvCreate fails and returns -1. Presumably libclntsh.so.9.0 looks for ORACLE_HOME and falls over when it doesn't find it.

Q: Is there a work around for this purely in terms of 9i version software?

One work around we've found is to install Instant Client. IC is intended to run in cases where there is no ORACLE_HOME set. This now acts as a gateway between our app and 9i. However, in order to make our app work with IC we've had to 'crle' the install path of IC. This is not so desirable because it adds to the admin burden.

Q. If the answer to the first question is 'no', is there another way of connecting to Oracle without modifying lib search paths?

I am including skeleton.cpp and the corresponding skeleton.ksh which demonstrates the problem.

Any advice is very much appreciated.
Adam

############## skeleton.cpp ########################

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <link.h>
#include <oci.h>
#include <oratypes.h>

int main(int argc, char *argv[])
{
OCIEnv *envhp;
sword (*MY_OCIEnvCreate)(...);
char* dlerr;
sword ociret;

if(argc < 1)
exit(1);

char *dllname = (char *)argv[1];

void *mydll = dlopen(dllname,RTLD_NOW|RTLD_GLOBAL);
if (mydll==NULL)
{
fprintf(stderr,"Error while loading Oracle module. dlopen() failed.\n"
"OS says: %s.\n",
(dlerr=dlerror())?dlerr:"");
exit(1);
}

MY_OCIEnvCreate = (sword(*)(...)) dlsym(mydll,"OCIEnvCreate");
if (MY_OCIEnvCreate == NULL)
{
fprintf(stderr,"Error while loading Oracle module function %s.\n"
"OS says: %s.\n",
"OCIEnvCreate",
(dlerr=dlerror())?dlerr:"");
exit(1);
}

ociret = MY_OCIEnvCreate(&envhp, OCI_DEFAULT, (dvoid *)0,
0, 0, 0, (size_t)0, (dvoid **)0);

if (OCI_SUCCESS != ociret)
{
fprintf(stderr, "OCI Error %ld occurred.\n", ociret);
exit(1);
}

return 0;
}

########### skeleton.ksh #####################

#!/bin/ksh -vx

ORA_DIR=/usr/opt/oracle/product/9.2.0.1.0
INSTCLI_DIR=/d0/adam/instantclient/instantclient10_1

#
# Make with 9i libs
#

CC -ldl -I$ORA_DIR/rdbms/demo -I$ORA_DIR/rdbms/public -o skeleton skeleton.cpp

if [[ $? -ne 0 ]]; then
print "ERROR: compile 1 failed"
exit 1
fi

#
# expect to succeed with ORACLE_HOME set and fail with ORACLE_HOME unset
#

export ORACLE_HOME=$ORA_DIR
skeleton $ORA_DIR/lib32/libclntsh.so
if [[ $? -ne 0 ]]; then
print "ERROR: unexpectedly failed in 9i on ORACLE_HOME set"
exit 1
fi

unset ORACLE_HOME
skeleton $ORA_DIR/lib32/libclntsh.so
if [[ $? -eq 0 ]]; then
print "ERROR: unexpectedly succeeded in 9i on ORACLE_HOME set"
exit 1
fi

#
# Make with Instance Client libs
#

CC -ldl -I$ORA_DIR/rdbms/demo -I$ORA_DIR/rdbms/public -o skeleton skeleton.cpp

if [[ $? -ne 0 ]]; then
print "ERROR: compile 2 failed"
exit 1
fi

#
# expect to succeed with ORACLE_HOME unset
#

skeleton $INSTCLI_DIR/libclntsh.so
if [[ $? -ne 0 ]]; then
print "ERROR: unexpectedly failed with Instance Client 10.1 and ORACLE_HOME set"
exit 1
fi

exit 0

############################################
Re: Problems with OCI without an environment (ORACLE_HOME not set) [message #178862 is a reply to message #178506] Fri, 23 June 2006 03:37 Go to previous message
adamb
Messages: 6
Registered: April 2006
Location: London, UK
Junior Member
After some investigation I have found a surprisingly simple solution to this problem. When inetd exec's a process, it provides a bare bones environment that comes from the /etc/default/login file. This environment can be extended using putenv(3C). Thus after dlopen/dlsym of clntsh, the program calls putenv with "ORACLE_HOME=/usr/opt/oracle/product/9.2.0.1.0" as argument. OCIEnvCreate and other OCI calls work fine after this.

Adam
Previous Topic: Question : [ORA-12560 TNS:protocol adapter error]
Next Topic: in pro*c
Goto Forum:
  


Current Time: Thu Nov 21 10:55:51 CST 2024