Change OCI dynamically
-
heidenbluth
- Posts: 56
- Joined: Mon 08 Nov 2004 19:01
- Location: Germany
Change OCI dynamically
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.
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.
-
heidenbluth
- Posts: 56
- Joined: Mon 08 Nov 2004 19:01
- Location: Germany
Same Behavior
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).
- Old OCI DLL is unloaded (OK)
- The other Oracle 11 DLLs keep loaded (why)
- New 10g DLLS are also loaded (OK).
-
heidenbluth
- Posts: 56
- Joined: Mon 08 Nov 2004 19:01
- Location: Germany
Replace call of GetOciClientVersion in DetectOci
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.
(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.
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.
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
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.
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.