> > > The ability to share handles, is one of the reason to use > > threads, isn't it? > > It would certainly be nice - but very hard to get right and safe. >
Tim, just a question, do you know if the C-Library of Orcale is threadsafe, so that when DBI would be able to share handles (in the long term), this is usefull when using Orcale. I guess it is so, just would like to get a confirmation, before I put any thoughs or work into makeing DBI able to share handles. The basic goal is to have just one database connection, which is shared by all threads. (At least to be able to do so) ---------------- So for now I have made a patch that makes DBI ithread safe, the way you suggested it. That means that every thread has it's own DBI enviroment and doesn't share any data or handles... > > The DBI needs a CLONE sub to 'isolate' the cloned dbistate struct > from the parent by creating a new one, initializing it, and doing > sv_setiv(get_sv(DBISTATE_PERLNAME,1), (IV)DBIS); to 'publish' the new > address. > CLONE now calls _clone_dbis() in DBI.xs, which calls dbi_bootinit() to setup a new and clean DBIS struct. > The DBI_LOCK mutex can be removed because it's not needed now there's > only one thread using an instance of the dbistate struct. > I didn't have removed anything of the old thread code, because I don't know if anybody using it. The DBI_LOCK etc. isn't enabled anyway because USE_THREADS is not set when USE_ITHREADS is set. At some places I had to disable the old thread code (e.g. in dispatch) when USE_ITHREAD is defined. > Add the 'owner' thread id to the dbistate struct. > thr_user is added which holds the pointer to the PerlInterpreter struct. thr_user in dbih_com_std_st is now also a PerlInterpreter pointer in case of USE_ITHREAD. > The dbi_last_h should be moved into the dbistate struct (but that > can wait as it's not really related to threads, just a cleanup). > Yes, should be done, but I didn't have done it for now, because I wanted to make as less as possible change to not break anything. > %DBI::installed_drh holds the handles of loaded drivers. > It needs to be cleared by the CLONE sub so that the next connect() > will re-call the drivers driver() method to get a new driver handle > that's associated with the new instance of the DBI for that thread. > done > To make that work each driver needs a CLONE sub that clears the > $drh variable that holds the drivers own driver handle. > Yes, each driver needs sub CLONE { $drh = undef ; } Addtionaly the driver must make sure it does not use any C globals. If you see a message like FATAL: DBI handle (type=1) is not owned by current thread in call to DBD::ODBC::dr::default_user (is 15d42a4, should 1c6c814) then you properbly have fogotten to add this to the driver. > To check that drivers have actually done that, the DBI's setup_handle > function can check the current thread id matches the thread id in > the dbistate struct. If not then warn. > I have added such a test to dispatch instead. This makes sure that any handle that is used is always belongs to the current thread. If not DBI dies, because otherwise it would segfault anyway. > I've probably missed stuff here but I'm pretty sure it's in the > right direction. > The thing you missed and which had added me some new grey hairs is, that because all C structs are allocated as an SV, they also get cloned. A problem arises when Perl tries to destroy such a cloned handle. This always happens when you have any open handle, while the CLONE is happen. Perl clones the handle (there is no way to avoid this) and because we don't use it in the new thread/Perl interpreter it get's destroyed, but since Perl does a stupid copy of the C struct, the data still points to the old thread. So it segfaults. I have solved this problem, that in case DESTROY and/or a dbi_clearcom is called for a handle that doesn't belongs to the current thread, they just do nothing. I append the patch. I have tested it with DBD::ODBC and DBD::Oracle on windows with Perl 5.8.0RC2. DBD::ODBC just needs to get the sub CLONE { $drh = undef ; } added. DBD::Oracle needs addtionaly the patch I had send some days ago (I didn't had the time to implement the CLONE patch we have discussed for DBD::Orcale, because it's some more work, because I need to move the global variables into the driver or any other handle to make it threads safe) I have written a small test program that starts an increasing number of threads which do some random database operations. It's a quick and dirty script, but I also append it. Maybe it usefull for somebody. Any comments are welcome :-) Gerald ------------------------------------------------------------- Gerald Richter ecos electronic communication services gmbh Internetconnect * Webserver/-design/-datenbanken * Consulting Post: Tulpenstrasse 5 D-55276 Dienheim b. Mainz E-Mail: [EMAIL PROTECTED] Voice: +49 6133 925131 WWW: http://www.ecos.de Fax: +49 6133 925152 -------------------------------------------------------------
dbi.patch
Description: Binary data
thrtest.pl
Description: Binary data