Tim Bunce wrote:
On Mon, Mar 03, 2003 at 10:16:07AM +1100, Stas Bekman wrote:

Tim Bunce wrote:

On Sun, Mar 02, 2003 at 02:21:41PM +1100, Stas Bekman wrote:

Seems like the $dbh->take_imp_data method will need driver involvement
to 'cleanse' the imp data by freeing everything not essential to
the connection - and hopefully that'll include all the SVs.

If SVs are required, for some reason, can they be made shared, or
replaced with a shared copy? (My perl threads api knowledge is a
bit rusty.)

There should be no perl datastructures involved at all in the pool storage.

Maybe not 'involved' but there's a strong chance the imp_dbh contains SV*'s.

I thought that drivers are pure C.


DBD::Foo's are a hybrid interfacing a pure C database API to a perl application.

But I've checked just checked a whole bunch of DBD's now...
Most do contain SV*'s in the imp_sth struct, but the imp_dbh doesn't
have any, so it almost seems like this isn't going to be a big issue
in practice.

There are some exceptions though... DBD::ODBC does have
        SV *odbc_err_handler; /* contains the error handler coderef */
but I think that could be moved into the $dbh attribute hash
in a new release. ["Paging Mr Urlwin"]
http://search.cpan.org/src/JURL/DBD-ODBC-1.04/dbdimp.h

And DBD::Sybase has the same, plus a row callback hook SV:
http://search.cpan.org/src/MEWP/DBD-Sybase-0.95/dbdimp.h
["Paging Mr. Peppler"]

OK, here is what I think.


I first wanted to implement the pooling transparent to the driver. Hence I needed to have something opaque that I can rip off and the re-use it later. Think of it as a heart. We can cut the heart off and then re-use it another body (simple, eh ;), but if it comes with all kind of attachements (other organs attached with veins) we may or may not be able to transplant the whole pack.

Since Tim suggested that it's the drivers that should handle the transplantation, it's now all simple. What we want to avoid is the low level physical connection process, in order to avoid that we give a chance to a driver to deposit some information about the connection (vital organs) in the central depository (transplants repository). Now when the driver connects on the next time, the repository lends the deposited information to the driver. Now it's up to the driver how to use it. As simple as that. DBI can provide examples on how this can be implemented, but only the driver knows the intricasies of its data, so only it can implement the right thing.

That's why I've suggested that this works cleanly if the driver's imp portion includes no SV*s. In case it does it's up to the driver to figure out how to give away a mirror of its private imp portion, including SV*s if any. In this case DBI by itself can't just memcpy the imp_dbh_st struct, but it has to perform a deep copy on SV*s (without affecting the reference count of the original SV*s). Depending on what kind of SV*s are stored in that private portion, another thread may or may not revive them. After all SV*s are just datastruct, so created by one interpreter and copied away as raw data, they can be revived by another interpreter, though that other interpreter won't destroy this data, since it has no clue it belongs to it.

So, I believe it's up to the driver to decide whether its data can be cloned and pooled or not. I believe some chunks of perl_clone() may help here.


Umm, I'm not sure if they'll be any issues about which thread does the cloning.
But I suspect that deep cloning would rarely be what's needed.

Cool.


So far I've played with DBD::mysql, which has no SV*s in its private imp and it works great.


It looks like others will require little or no change either.

Some, like DBD::Interbase may have some other issues though.
It does it's own explicit housekeeping of statement handles
by keeping them in a list rooted in the imp_dbh:
http://search.cpan.org/src/EDPRATOMO/DBD-InterBase-0.40/dbdimp.h

Here again, I think this translates to the driver implementing the
take_imp_data() method and it either dealing with all the cleanup
issues or croaking if it can't. The driver needs to view the
take_imp_data method as being nearly the same as disconnect+DESTROY
only not actually calling the database API to disconnect.

Exactly.


All SVs and other state can be cleaned up and feeded - in the case
of Interbase that probably translates into forcing destruction of
any statement handles that still exist when take_imp_data() is called.
All that needs to remain is the underlying database API conection data.

Perfect.


Actually, it ought to have been:

struct imp_dbh_st {
    dbih_dbc_t *com;        /*  POINTER to com MUST be first */
    imp_t imp;
}

which would then make the drivers independant of the changes to the
size of the com structure.

I guess drivers could already do that now, so in the future they don't have to do anything to adher to the change.


The DBI would have to do it as it supplies a whole bunch of macros
that access the com element.

I was talking about non-com elements, about which DBI has no clue what are they. So they can be several elements or they can be a pointer to a separate struct.


It's on my list of things to do in the future. But I'd like to do
it as part of a general overhaul of the DBI/DBD interface and flag
the results a DBI 2.00. But I'm not sure when that'll happen.


The issue being that changing the DBI/DBD interface forces a site to recompile all their drivers, which makes installing that release a "big deal". Hence my desire to not make changes there very often, and when I do to make several together.

That makes a perfect sense. ;)




__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com



Reply via email to