Stas, I'm getting bounces for my emails to you: <[EMAIL PROTECTED]>: 195.154.174.36 does not like recipient. Remote host said: 554 <mail00.svc.cra.dublin.eircom.net[159.134.118.16]>: Client host rejected: Access denied Giving up on 195.154.174.36.
Are you getting my emails? You seem to be as you've replied to at least one that I've had a bounce for. Tim. p.s. If Stas doesn't reply to this today, I'd appreciate it if someone could forward a copy of this and my recent emails to him. Thanks. On Thu, Feb 27, 2003 at 10:30:52AM +0000, Tim Bunce wrote: > On Thu, Feb 27, 2003 at 11:33:54AM +1100, Stas Bekman wrote: > > Tim Bunce wrote: > > > > >>>The 'implementors data' (after the DBI common data at the start) holds > > >>>data that's private to the driver, like pointers to the database > > >>>API objects like connection handles etc. > > >> > > >>That's exactly what I'm sharing. Though we have to agree that if the DBD > > >>chooses to include anything that has to do with Perl (SVs, references to > > >>my_perl, etc) this DBD can't participate in the world domination scheme. > > >>;) > > > > > > > > >Since a driver only shares implementors data with itself it'll know > > >what it can and can't use. Since I'm proposing the the driver copy > > >the implementors data and not just point to it then, at the moment > > >the copying is happening then even data stored in non-magical SV's > > >ought to be safe to access because, given the pool model, no other > > >thread would be touching it at the same time. > > > > I'd first try to get away without copying if possible. And pursue the > > copying next if that doesn't work. > > Er, why? Isn't the only alternative to copying, pointing? > And isn't pointing worse? > > > > >>>On the borrowers side we need to pass in the borrowed ID to the > > >>>connect() call so the driver can use it. For example: > > >>>my $dbh => DBI->connect($dsn, $user, $pass, { UseID => $id }); > > >> > > >>Nuh, it can be transparent for the user API. Just lock the pool, check > > >>whether there are free items, borrow if any or do a normal login and > > >>store otherwise. I don't think the top level connect() API should change > > >>at all, other than finding a way to turn the pooling on/off. > > > > > > > > >But how do you tell the driver that it should be reusing the > > >implementors data from an exisiting connection? > > > > I don't. My design is to make this transparent to the drivers. As you can > > see from my code, I overload the driver's _login function and accomplish > > what I need. > > That presumes that all drivers use a _login function, which may not > be true. And I think that trying to be transparent to the drivers > will never be safe enough. There's always a strong possibility that > the implementors data contains SV* etc's the are owned by a different > interpreter. On the other hand, the driver changes required are > minor and I doubt there would be a problem getting them implemented. > > > > >>>For safety and simplisity it would seem best to copy the implementors > > >>>data structure and overwrite anything that needs overwriting. > > >> > > >>Yes, but the problem is when $dbh is destroyed the private implementation > > >>is destroyed as well. So no matter if you copy it or not, if we have no > > >>way to prevent the destruction/cleanup of the implementators data, we are > > >>in trouble. That's one of the problems that I'm stumbled with. > > > > > > > > >Hence my proposal to have a flag on the handle to say it's been > > >borrowed. If it's destroyed in that case then it ought not to > > >cleanup the implementators data (just warn). > > > > > >Ah, actually the InactiveDestroy flag could serve that purpose for > > >the time being (but without the warning). Cute. > > > > So, you say that we absolutely must have drivers to co-operate with DBI to > > accomplish that. I thought that it'd be possible for DBI simply to skip the > > destruction calls to the drivers data. > > Setting the existing InactiveDestroy attribute will achieve that much. > Using a new flag would just allow us to fine-tune the semantics, like > issuing a warning. > > > >>>>These are the open issues: > > >>>> > > >>>>2. I need a support from DBI to help me access the *really* private > > >>>>data in struct imp_dbh_st, because the following is a hack: > > >>>> > > >>>> D_imp_dbh(dbh); > > >>>> imp_dbh->mysql = ((imp_dbh_t *)imp_dbh_new)->mysql; > > >>> > > >>>Perhaps, but why exactly are you calling it a hack? > > >> > > >>because it calls ->mysql. > > > > > >That's why the driver itself needs to be the one to do the copying > > >of the 'template' implementors data. Only it can know what's needed. > > > > I'm not 100% sure. Here is what I've figured from messing with debugger: > > > > The driver knows the size of imd_dbh_st. DBI knows the size of the first > > member of imd_dbh_st (or am I wrong?). > > So we could have a driver function > > which gives us an access to the point where the "really" private data > > starts. > > Yes, and yes. > > But only the driver knows what's in that data and thus what needs to be > re-initialised for use in a different thread - like SVs. > > > >(Although I propose to let the DBI do the copying when it alloc's > > >the implementors data structure and set a flag for the driver which > > >could then skip most of it's own setup knowing that the struct > > >elements have been copied already.) > > > > well, that's exactly what I was after ;) > > :) > > > >Um, the allocates/finishes/puts seems wrong. The pool thread is the only > > >one to make real connections (in response to requests). Having made the > > >connection the imp data is then 'borrowed' and passed back to the thread > > >that requested the connection. That requesting thread then does a > > > $dbh = DBI->connect(..., { UseID => $id }) > > >to get a $dbh in it's own thread but using the imp data from the pool. > > > > So you are proposing to use the normal grow() concept. Which introduces two > > problems. The first just inconvenience as you have to pass the arguments > > and handle failures, etc... The second is the serialization of connect(). > > What you suggest is the following: > > > > the pool is empty, let's grow it: > > > > lock # here all other threads block > > switch the perl context to the parent (pool) perl thread; > > connect (); > > pool the object and lend it to the requesting thread > > switch the perl context back to thread's perl > > unlock > > > > this could be quite a bottleneck. > > The key point being that the connect could be slow while holding the lock. > Okay, I see that. > > > in my design, each thread does its own connect and then deposit the object > > to the pool. No bottleneck whatsoever. Other than the pool management > > blocking. > > Umm [thinks] okay, there's no reason why the connections in the pool > can't themselves be created via > $dbh = DBI->connect(..., { UseID => $id }) > where the $id has come from a connection created outside the pool. > > We just need a way to 'take' imp data instead of 'borrow' it, so > the handle that's left behind is effectively dead and won't warn > when it's destroyed. That may be as simple as also setting > InactiveDestroy. > > > > >>now that it exits, chances are that the data in pool may go invalid. > > > > > >"data in pool may go invalid" Eh? > > > > remember, I'm talking about threads allocating memory, not the parent > > thread. When the thread exists depending on how the memory was allocated, > > the memory could get freed. > > So copy and reinit as needed, don't point. > > > Let's see if I can summarize where we're at (from the DBI prespective)... > > my $id = $dbh->borrow_imp_data; > > Sets a flag to inidcate that the imp data is in use by > another thread. Returns a token for the imp data, possibly > simply the address, but could also be the whole imp data > structure. Using the whole struct is appealing because it > avoids a race hazard - if borrow_id sets a flag before > returning then whichever thread uses the id will see that > flag already set. > > my $id = $dbh->take_imp_data; > > As above but indicates that the imp data won't be returned > and the handle is effectively dead. > > $dbh->restore_imp_data; > > Indicates that the thread that borrowed the imp data has > finished using it. > > $dbh = DBI->connect(..., { UseImpData => $id }) > > Creates a new dbh and initialises it with a copy of the given imp data. > Also sets a flag to indicate that the imp data is borrowed. > > Does that give you all the mechanisms you need to build on? > > Tim.