Re: libpq++

Поиск
Список
Период
Сортировка
От Justin Banks
Тема Re: libpq++
Дата
Msg-id 15084.54539.44529.709222@dervish.mr-boo.com
обсуждение исходный текст
Ответ на Re: libpq++  (Bruce Momjian <pgman@candle.pha.pa.us>)
Список pgsql-interfaces
>>>>> "Bruce" == Bruce Momjian <pgman@candle.pha.pa.us> writes:
 Bruce> I am not so much the libpq++ maintainer as the one who applies Bruce> people's patches.  There is an interfaces
listthat would love to Bruce> hear about your work.  I am CC'ing them on this.  We certainly need Bruce> libpq++
improvements. If you would prefer not to deal with the Bruce> interfaces list, send something to me and I will send it
overthere.
 

Here's what I've done. The following code will create a number of different
connections to the B.E., even though there's no reason to have more than
one. This prevents one from inheriting PgDatabase, and then creating an array
of 100 or so of those objects.

#include <iostream.h>
#include <stdlib.h>
#include <libpq++.h>


class base : public PgDatabase { public:   base() {     cout << "base class instantiating" << endl;
Connect("host=dbdbname=golem user=golemadmin password=bleen");   }   virtual ~base() {     cout << "Base class
destructing"<< endl;   }
 

};

class derived : public base { public:   derived() {     cout << "derived class instantiating" << endl;   }   ~derived()
{    cout << "derived class destructing" << endl;   }
 
};

int 
main(int argc, char* argv[]) { int cnt, tuples; derived* classes, *ptr; derived single;
 if(argc > 1)   cnt = atoi(argv[1]); else   cnt = 5;
 cout << "getting array of " << cnt << " objects" << endl; classes = new derived[cnt];
 cout << "array allocated, sleeping for validation" << endl; sleep(5); for(int i = 0; i < cnt; i++) {   cout <<
"testingobject " << i << endl;   ptr = &(classes[i]);   ptr->Exec("select * from defaults");   tuples = ptr->Tuples();
cout << "got " << tuples << " tuples" << endl;   for(int j = 0; j < tuples; j++) {     cout << "4th field is " <<
ptr->GetValue(j,4) << endl;   } } delete[] classes;
 
 cout << "aggregates deleted" << endl; single.Exec("select table_name from tables limit 1"); cout << "exec of single
finished"<< endl; cout << "value is " << single.GetValue(0, 0) << endl; exit(0);
 
}


What I'd like to have happen is for a total of one connection to the database
to be made, and have all these objects share that connection transparently. I
made this happen by using a shared memory segment to store the connection
pointer. Here's the diff. It doesn't seem to break anything, but then again,
my coverage is rather limited at this point.

Diff follows :

--- pgconnection.cc.orig    Sun Apr 29 16:09:02 2001
+++ pgconnection.cc    Sun Apr 29 21:35:36 2001
@@ -17,7 +17,6 @@#include "pgconnection.h"
-// ****************************************************************//// PgConnection Implementation
@@ -54,7 +53,15 @@// close down the connection if there is onevoid PgConnection::CloseConnection() {
-  // if the connection is open, close it first
+#if USING_SYSV_IPC == 1
+  struct shmid_ds shminfo;
+
+  shmctl(shmid, IPC_STAT, &shminfo);
+  //
+  // if we're the only one left ...
+  //
+  if(shminfo.shm_nattch == 1) {
+#endif      if ( pgCloseConnection ) {           if(pgResult) PQclear(pgResult);       pgResult=NULL;
@@ -62,6 +69,10 @@       pgConn=NULL;       pgCloseConnection=0;  }
+#if USING_SYSV_IPC == 1
+  }
+  shmdt(addr);
+#endif}
@@ -69,11 +80,60 @@// establish a connection to a backendConnStatusType PgConnection::Connect(const char* conninfo){
+#if USING_SYSV_IPC == 1
+  int key = (int)getpid();
+  struct shmid_ds shminfo;
+#endif
+  // if the connection is open, close it first  CloseConnection();  // Connect to the database
+#if USING_SYSV_IPC == 1
+  if((shmid = shmget(key, sizeof(addr), IPC_CREAT|SHM_W|SHM_R)) >= 0) {
+    if((addr = (int*)shmat(shmid, 0, 0)) > 0) {
+      //
+      // now, we have our segment. If we're the first attacher, then we need
+      // to do the connect. If we're not the first attacher, then the
+      // connection is already made, we just need to check and make sure
+      // it's okay, connecting again if we have to.
+      //
+      if(shmctl(shmid, IPC_STAT, &shminfo) == 0) {
+        if(shminfo.shm_nattch == 1) {
+          pgConn = PQconnectdb(conninfo);
+          *addr = (int)pgConn;
+        }
+        else {
+          pgConn = (PGconn*)*addr;
+          if(Status() == CONNECTION_BAD) {
+            pgConn = PQconnectdb(conninfo);
+            *addr = (int)pgConn;
+          }
+        }
+      }
+      else {
+        //
+        // fallback to safe connection
+        //
+        pgConn = PQconnectdb(conninfo);
+      }
+    }
+    else {
+      //
+      // fallback to safe connection
+      //
+      pgConn = PQconnectdb(conninfo);
+    }
+  }
+  else {
+    // 
+    // fallback to safe connection
+    //
+    pgConn = PQconnectdb(conninfo);
+  }
+#else  pgConn = PQconnectdb(conninfo);
+#endif  // Now we have a connection we must close (even if it's bad!)  pgCloseConnection = 1;
--- pgconnection.h.orig    Sun Apr 29 16:09:54 2001
+++ pgconnection.h    Sun Apr 29 17:07:57 2001
@@ -46,6 +46,15 @@using namespace std;#endif
+#if HAVE_SYS_SHM_H == 1 && HAVE_SYS_IPC_H == 1
+ #include <sys/types.h>
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+ #include <unistd.h>
+ #define USING_SYSV_IPC 1
+#else
+ #define USING_SYSV_IPC 0
+#endif// ****************************************************************//
@@ -91,6 +100,9 @@// so make copy constructor and assignment op private.   PgConnection(const PgConnection&);
PgConnection&operator= (const PgConnection&);
 
+#if USING_SYSV_IPC == 1
+  int shmid, *addr;
+#endif};#endif    // PGCONNECTION_H

I think that's it. I've got more at work, so I may have missed something, but
I don't think so.

-justinb

-- 
Justin Banks @ home
Distrust any enterprise that requires new clothes. -Thoreau



В списке pgsql-interfaces по дате отправления:

Предыдущее
От: "J. T. Vermeulen"
Дата:
Сообщение: Re: Re: libpq++
Следующее
От: Justin Banks
Дата:
Сообщение: Re: libpq++