Change OCI dynamically

Discussion of open issues, suggestions and bugs regarding ODAC (Oracle Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
heidenbluth
Posts: 56
Joined: Mon 08 Nov 2004 19:01
Location: Germany

Change OCI dynamically

Post by heidenbluth » Wed 23 Feb 2011 08:26

Hello,

I want to give the user the option to change the OCI on re-connect by setting OraCall-OCIDLL. Unfortunately, FreeOCI unloads only the master OCI.DLL, but a couple of other Oracle libraries keep loaded.

If you load another OCI DLL it reuses the already loaded subordinate DLLs from the wrong Oracle home.

How can I unload ALL Oracle DLLs?

A simple testcase looks as follows:

begin
InitOci;
FreeOci;
end;

After that, a process explorer shows some Oracle DLLs are still in memory.

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Post by AlexP » Wed 23 Feb 2011 12:51

Hello,

To change Oracle Client you do not need to change the OCI library, you should change only the OraSession.Home property.
When the Oracle Home is changed, then correct dll's will be automatically loaded.

heidenbluth
Posts: 56
Joined: Mon 08 Nov 2004 19:01
Location: Germany

Same Behavior

Post by heidenbluth » Wed 23 Feb 2011 13:48

I dropped a TOraSession on a blank Mainform. I Connected at Designtime using Home_Oracle11, disconnected and connected again using Home_Oracle10. Now I run the ProcessExplorer fron SysInternals.com:
- Old OCI DLL is unloaded (OK)
- The other Oracle 11 DLLs keep loaded (why)
- New 10g DLLS are also loaded (OK).

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Post by AlexP » Wed 23 Feb 2011 14:46

Hello,

I think such behaviour is connected with the peculiarities of the OCI.dll work, because if OCI.dll loads necessary *.dlls on its own, then it should unload them itself, and if it doesn't do this, then it's needed for work.

heidenbluth
Posts: 56
Joined: Mon 08 Nov 2004 19:01
Location: Germany

Replace call of GetOciClientVersion in DetectOci

Post by heidenbluth » Fri 25 Feb 2011 08:36

The problem may be related on Oracles poor handling of unloading DLLs. I would guess they didn't consider the option to change it. But ODAC shouldn't make things worse. Please have a look at the following scenario:

(1) We call DetectOCI to get information about Oracle Homes and TNS aliases.
--> This calls GetOciClientVersion function from the default OCI DLL including LoadLibraryEx
--> As a result, all subordinate DLLs from the Default Oracle Home are also loaded.

(2) You change OracleHome and connect
--> This unloads the default OCI.DLL and keeps the other subordinate libraries in memory
--> Then the new OCI.DLL will be loaded.

(3) Depending on the versions of the two Oracle clients, you can get a mix of libraries from both homes. For example if you deal with an Oracle 11.1 and an Oracle 11.2 client the DLL names are identical and will be reused from the default OCI which is partly still in memory.

Suggestions:
(1) The least you can do is please substitute the GetOciClientVersion call with an GetFileVersionInfo call. This doesn't load the whole bunch of subordinate libraries and gives you the chance to load all libraries from the OracleHome of your choice.
(2) This is a more advanced task. Maybe there is a way of helping Oracle to unload the libraries. I am no expert in this and I cannot suggest how to do it.

Please help at least with something like suggestion #1. :)

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Post by AlexP » Fri 25 Feb 2011 11:38

Hello,

Calling of the GetFileVersionInfo method does not guarantee that the received version is correct, because this information is easy to change. That's why it's better to call the standard OciClientVersion method.

Really, if you load a newer oci.dll (for example, 10.2) and call the OciClientVersion method, and then load an earlier oci.dll (for example, 10.1) and call the OciClientVersion method, access violation occurs.

We will try to resolve the problem.
We will notify you as soon as we have any results.

heidenbluth
Posts: 56
Joined: Mon 08 Nov 2004 19:01
Location: Germany

Post by heidenbluth » Fri 25 Feb 2011 12:34

I am not sure who would manipulate the version information in the file ressource. If you are uneasy you can re-discover the information by function call once the library has been loaded. But it seems no good to load the libraries without beeing sure of using it.

Our customer has an Oracle 11.1 client as default and an Oracle 11.2 client in use. Our application uses DevExpress grids for displaying data. He got access violation errors when using the FilterRow. We got some feedback using Eurekalog and discovered that the application used a mix of Oracle 11.1 subordinate DLLs and Oracle 11.2 OCI.DLL. After changig the default to 11.2 the problem has been resolved.

We got similiar problems before, for example an exception "entry point of xxxxx not found in DLLxxxxx", because the newer OCI DLL doesn't find functions in the already loaded older subordinate DLLs.

Please consider that this is also a performance issue. Many customers have their Oracle client installed on a network drive. Loading the OCI with all its subordinary libraries for the only purpose to read the version number costs a couple of seconds. If you intend to allow the application user to choosing the Oracle client, the chances are good that you have preloaded the entire OCI just for fun. Furthermore, you have the stability problems discussed before.

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Post by AlexP » Tue 01 Mar 2011 13:01

Hello,

These *.dlls are loaded not only when receiving the client version, but also when calling other methods from OCI.DLL. That's why defining of the client version with the help of the file version won't solve this problem. We are working on solving this problem.

Post Reply