Subject Re: [IBO] IBO with Multithreading and connection pool
Author Helen Borrie
At 08:20 PM 28/07/2005 +0000, you wrote:
>We're developing a multithreaded app using D5 Ent with IBO4, FB 1. We
>have implemented our own connection pool mechanism, where a Firebird
>connection comprises of an IB_Connection and an IB_Transaction placed
>on a TDataModule.
>The application can create multiples of such datamodules, so as to
>maintain a pool of free open connections.
>The processing is performed in another set of DataModule objects,
>which are created as required when processing and freed once complete.
>Each processing object has multiple TIBOQuery components, and an
>IB_Session (which is the first component listed inside of the dfm when
>opened as text - i hope this is the meaning of 'created first').
>The processing objects' constructor(thus running in the main thread)
>picks one of the free connection Datamodules and links the IBOQuery's
>IB_Connection and IB_Transaction pointers to the components on the
>connection datamodule. It also links the IB_Session to the
>Only after this is over that the thread kicks in and runs sqls through
>the IBOQuerys.
>Note that ib components are not being created at runtime (through
>code) because i prefer to have the compile-time fieldname checks.
>The connection is through TCPIP.
>There doesnt seem to be a problem with the overall code because the
>pool also has BDE components linking to an oracle db in a similar
>fashion, and those work fine (linking through uniquely generated
>DatabaseName and SessionName properties)

The connection architecture of IBO is NOT the same as the BDE. The concept
of "Session" is much more restricted in the IBO interface because, unlike
the BDE, IBO is (1) designed for multiple transactions (and cross-database
transactions, of course) and (2) the multi-generational architecture of
Firebird and IB.

>Now, we have faced several kinds of errors, depending on where we
>place the TIB_Session and TIB_Transaction. I would like to have your
>comments on this mechanism i have used.

The data object collection for *each* thread must consist of everything
needed by the thread, beginning with its own distinct TIB_Session Your
architecture is not correct. You cannot share database or data access
objects across threads.

>Also, is the TIB_Session in the right datamodule? (with the IBOQuerys,
>and dynamically linked to an IB_Connection)

No. Create everything in one datamodule - with strict attention to
creation order (TIB_Session must be the first). Remove the
statement Application.CreateForm(TdtmMyData, dtmMyData);
from your DPR file and have your application create and destroy the
datamodule as required at run-time.

The objects should never refer to any objects beyond the boundaries of the
thread so, if you have forms to which these objects are bound, they should
be excluded from the DPR as well, and created and destroyed for the thread
in a timely manner, along with the datamodule. By a timely manner I mean
that, if the thread is to open with an active GUI, you must create the
datamodule before the GUI pieces, to avoid having the forms reference data
access objects that don't exist.

>Also, i have read in an earlier post about a 'SetSession' function,
>though this is not documented anywhere in the help. Is this a possible
>mechanism to explicitly link an IBOQuery to an IB_Session (even though
>the session was possibly created sometime after the query was

It is not an exposed method, even in the native statement classes. It is
used internally by components during the setting of the IB_Session
property. In the case of an IBOQuery, it is applicable to the wrapping
TIB_Dataset, MyIBOQuery.InternalDataset. You might be interested in this
method if you were writing custom components based on the native IBO classes...

Pay attention to the IB_Session property. Keep all IB_Session references
strictly inside the modules created for your threads. For all components
that expose an IB_Session property in the IDE, drop down the selector and
select the correct IB_Session object explicitly.

If you also have data components in the main thread, then it's recommended
that you drop an explicit TIB_Session into your main form or datamodule,
for use by the main thread alone.