[PATCHES] libpq object hooks patch

2008-04-15 Thread Andrew Chernow
Here is an updated version of the object hooks patch.  It now supports a 
list of hooks for a PGconn, and PGresult.  This had to re-introduce the 
concept of hook name.  Being that there is now a list, you need a way to 
reference an item of that list.


Also added PQobjectHooks and PQresultObjectHooks, to get a pointer to 
the conn or result hook list.  PQmakeResult must allow the ability to 
pass a list of object hooks in.  So, PQresultObjectHooks was born. 
pqtypes doesn't need (at least at this time) PQobjectHooks but leaving 
it out felt unbalanced.


Note: PQhookData and PQresultHookData can be removed.  There 
functionality can be reproduced by an API user issuing PQobjectHooks or 
PQresultObjectHooks and manually looking for there hook (normaly to get 
at the hook-data).  Basically, an API user would do themselves what 
PQhookData is doing.


--
Andrew Chernow
eSilo, LLC
every bit counts
http://www.esilo.com/
Index: exports.txt
===
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/exports.txt,v
retrieving revision 1.19
diff -C6 -r1.19 exports.txt
*** exports.txt 19 Mar 2008 00:39:33 -  1.19
--- exports.txt 15 Apr 2008 17:18:38 -
***
*** 138,143 
--- 138,151 
  PQsendDescribePortal  136
  lo_truncate   137
  PQconnectionUsedPassword  138
  pg_valid_server_encoding_id 139
  PQconnectionNeedsPassword 140
  lo_import_with_oid  141
+ PQmakeResult  142
+ PQsetvalue143
+ PQresultAlloc 144
+ PQaddObjectHooks  145
+ PQhookData146
+ PQresultHookData  147
+ PQobjectHooks 148
+ PQresultObjectHooks   149
\ No newline at end of file
Index: fe-connect.c
===
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.357
diff -C6 -r1.357 fe-connect.c
*** fe-connect.c31 Mar 2008 02:43:14 -  1.357
--- fe-connect.c15 Apr 2008 17:18:39 -
***
*** 241,253 
 PQExpBuffer errorMessage);
  static char *pwdfMatchesString(char *buf, char *token);
  static char *PasswordFromFile(char *hostname, char *port, char *dbname,
 char *username);
  static void default_threadlock(int acquire);
  
- 
  /* global variable because fe-auth.c needs to access it */
  pgthreadlock_t pg_g_threadlock = default_threadlock;
  
  
  /*
   *Connecting to a Database
--- 241,252 
***
*** 979,990 
--- 978,990 
   * o  If your backend wants to use Kerberos authentication then you 
must
   *supply both a host name and a host address, otherwise this 
function
   *may block on gethostname.
   *
   * 
   */
+ 
  PostgresPollingStatusType
  PQconnectPoll(PGconn *conn)
  {
PGresult   *res;
charsebuf[256];
  
***
*** 1875,1887 
 * the connection structure must be freed).
 */
conn-status = CONNECTION_BAD;
return PGRES_POLLING_FAILED;
  }
  
- 
  /*
   * makeEmptyPGconn
   * - create a PGconn data structure with (as yet) no interesting data
   */
  static PGconn *
  makeEmptyPGconn(void)
--- 1875,1886 
***
*** 1970,1981 
--- 1969,1998 
   * release data that is to be held for the life of the PGconn structure.
   * If a value ought to be cleared/freed during PQreset(), do it there not 
here.
   */
  static void
  freePGconn(PGconn *conn)
  {
+   int i;
+ 
+   for(i=0; i  conn-objHooksCount; i++)
+   {
+   if(conn-objHooks[i].connDestroy)
+   {
+   conn-objHooks[i].connDestroy((const PGconn *)conn);
+   free(conn-objHooks[i].name);
+   }
+   }
+ 
+   if(conn-objHooks)
+   {
+   free(conn-objHooks);
+   conn-objHooks = NULL;
+   conn-objHooksCount = conn-objHooksSize = 0;
+   }
+ 
if (conn-pghost)
free(conn-pghost);
if (conn-pghostaddr)
free(conn-pghostaddr);
if (conn-pgport)
free(conn-pgport);
***
*** 2152,2164 
--- 2169,2189 
  {
if (conn)
{
closePGconn(conn);
  
if (connectDBStart(conn))
+   {
+   int i;
+ 
(void) connectDBComplete(conn);
+ 
+   for(i=0; i  conn-objHooksCount; i++)
+   if(conn-objHooks[i].connReset)
+   conn-objHooks[i].connReset((const 
PGconn *)conn);
+   }
}
  }
  
  
  /*
   * PQresetStart:
***
*** 2176,2198 
return connectDBStart(conn);
}
  
return 0;
  }
  
- 
  

Re: [PATCHES] libpq object hooks patch

2008-04-15 Thread Andrew Chernow

Andrew Chernow wrote:
Here is an updated version of the object hooks patch.  It now supports a 
list of hooks for a PGconn, and PGresult.  This had to re-introduce the 
concept of hook name.  Being that there is now a list, you need a way to 
reference an item of that list.


Also added PQobjectHooks and PQresultObjectHooks, to get a pointer to 
the conn or result hook list.  PQmakeResult must allow the ability to 
pass a list of object hooks in.  So, PQresultObjectHooks was born. 
pqtypes doesn't need (at least at this time) PQobjectHooks but leaving 
it out felt unbalanced.


Note: PQhookData and PQresultHookData can be removed.  There 
functionality can be reproduced by an API user issuing PQobjectHooks or 
PQresultObjectHooks and manually looking for there hook (normaly to get 
at the hook-data).  Basically, an API user would do themselves what 
PQhookData is doing.





Made some changes:

1. Removed the hookName argument to PQaddObjectHooks, since its in the 
supplied PQobjectHooks struct.  I think the argument was lingering from 
a previous patch.


2. Added the ability to install global object hooks: 
PQaddGlobalObjectHooks(PGobjectHooks*).  The header docs for this 
function warns that it should only be used before calling libpq 
functions or creating application threads.  There are no management 
functions for global hooks, like get or remove.  If you add global 
object hooks, your stuck with them until process death.


3. There is a new internal pqInitObjectHooks(PGconn *) that installs the 
global object hooks on new conns in the CONNECTION_OK status.  I call 
this function within PQconnectPoll (3 different locations).  This will 
call PQaddObjectHooks(conn) for each global hook (so global hooks are 
always at the front of a conn's hook list).  pqInitObjectHooks checks to 
see if conn-objHooksCount  0 and if it is, the request is ignored and 
the function returns success.  This only happens during a PQreset and 
PQresetPoll.


// global
PQaddGlobalObjectHooks(libpq_debugger_hook);

// per-conn
PQaddObjectHooks(conn, session_manager_hook);

Since the existing list of object hooks is scanned for duplicate names 
when adding them, you will never run into duplicate object hooks in a 
connection (or in the global list).  If the two examples above were both 
called by an application, the per-conn call would fail.


--
Andrew Chernow
eSilo, LLC
every bit counts
http://www.esilo.com/
? exports.list
? libpq.so.5.2
? object_hooks.patch
Index: exports.txt
===
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/exports.txt,v
retrieving revision 1.19
diff -C6 -r1.19 exports.txt
*** exports.txt 19 Mar 2008 00:39:33 -  1.19
--- exports.txt 16 Apr 2008 01:14:40 -
***
*** 138,143 
--- 138,152 
  PQsendDescribePortal  136
  lo_truncate   137
  PQconnectionUsedPassword  138
  pg_valid_server_encoding_id 139
  PQconnectionNeedsPassword 140
  lo_import_with_oid  141
+ PQmakeResult  142
+ PQsetvalue143
+ PQresultAlloc 144
+ PQaddObjectHooks  145
+ PQhookData146
+ PQresultHookData  147
+ PQobjectHooks 148
+ PQresultObjectHooks   149
+ PQaddGlobalObjectHooks150
\ No newline at end of file
Index: fe-connect.c
===
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.357
diff -C6 -r1.357 fe-connect.c
*** fe-connect.c31 Mar 2008 02:43:14 -  1.357
--- fe-connect.c16 Apr 2008 01:14:40 -
***
*** 241,253 
 PQExpBuffer errorMessage);
  static char *pwdfMatchesString(char *buf, char *token);
  static char *PasswordFromFile(char *hostname, char *port, char *dbname,
 char *username);
  static void default_threadlock(int acquire);
  
- 
  /* global variable because fe-auth.c needs to access it */
  pgthreadlock_t pg_g_threadlock = default_threadlock;
  
  
  /*
   *Connecting to a Database
--- 241,252 
***
*** 979,990 
--- 978,990 
   * o  If your backend wants to use Kerberos authentication then you 
must
   *supply both a host name and a host address, otherwise this 
function
   *may block on gethostname.
   *
   * 
   */
+ 
  PostgresPollingStatusType
  PQconnectPoll(PGconn *conn)
  {
PGresult   *res;
charsebuf[256];
  
***
*** 998,1009 
--- 998,1010 
 * We really shouldn't have been polled in these two 
cases, but we
 * can handle it.
 */
case CONNECTION_BAD:
return PGRES_POLLING_FAILED;
case CONNECTION_OK:
+