Re: libpq object hooks - Mailing list pgsql-patches
From | Merlin Moncure |
---|---|
Subject | Re: libpq object hooks |
Date | |
Msg-id | b42b73150805161249wb67b065le957ef1c0cdaefec@mail.gmail.com Whole thread Raw |
In response to | Re: libpq object hooks (Andrew Chernow <ac@esilo.com>) |
Responses |
Re: libpq object hooks
Re: libpq object hooks |
List | pgsql-patches |
On Fri, May 16, 2008 at 2:34 PM, Andrew Chernow <ac@esilo.com> wrote: > Tom Lane wrote: >> >> typedef void (*PGeventProc) (PGeventId eventId, const void *eventInfo, >> void *passthrough); >> >> int PQregisterEventProc(PGconn *conn, PGeventProc proc, void >> *passthrough); > The above prototypes will work and we will add our 'event instance pointer' > to the event info structures. Should have a patch shortly. Right. I actually overlooked the 'passthrough' in PQregisterEventProc. It turns out that we are still not quite on the same page and this needs to be clarified before we move on. The passthrough cannot exist...the correct prototypes (reasoning will follow) are: typedef void (*PGeventProc) (PGeventId eventId, const void *eventInfo); int PQregisterEventProc(PGconn *conn, PGeventProc proc); PQhookData(const PGconn* conn, PGeventProc proc); ...etc. The purpose of the callbacks is to allow a hooking library to establish private data that is associated with a PGconn or a PGresult. Invoking PQregisterEventProc tells libpq 'I am interested in doing this', for the supplied PGconn, future results created with that connection, and (if PGconn is passed as null), all future connections. Once that is established, libpq begins telling the hooking library when and what needs to be allocated or deleted. This is done for both connections and results at the appropriate times and the management always occurs inside a callback function. Thus, while the hooking library controls what is in the state data, _it does not control when it is created or destroyed_. Passing a void* into PQregisterEventProc suggests that is the wrapper's purvue to establish the private information. It isn't, and it can't be..it's as simple as that. For example, consider that 'hooked' PGconn then produces a result. If a passthrough as Tom suggested were passed around, what would you do to it when the connection was freed (which throws a connection closing event)? What exactly is passthrough pointing to in a result copy event? If passed around as a single poitner, they are not defined.These are pointers to different structures who are created at particular times that only libpq knows. All of the callbacks (except for possibly conn reset) are basically allocation and deletion events. For example, result create is libpq telling the hooking library: 'a result is coming, please initialize your result extensions now'. At that point, a very particular structure is passed back to the hooking library: { const PGconn* conn; // the source conn the result const void *conn_state; // the conn's private state (it might be interesting, and we don't want to look it up later) const PGresult* res; // the new result's poiter void *out_res_state; // we are going to allocate something and set this in the callback } As you can see, there is more going on here than a single passthrough pointer can handle. We are in fact doing what a passthrough provides in principle. I can certainly understand why our original 'lookup by name' concept threw up a smokescreen (it did obfuscate the passing requirements), but hooking can't be serviced by a single pointer set at callback registration. With the above prototypes and carefully designed structures, everything feels natural. libpq is defining exactly what is supposed to happen, and the structure parameters define what is coming in and out. Things are being 'passed through'...but in a more discrete way. merlin
pgsql-patches by date: