Re: Handling notices, warnings, etc.

"Joel Nothman" <[email protected]>
Newsgroups gmane.comp.python.db.psycopg.devel
Message-ID <[email protected]>

On Tue, 02 Jun 2009 01:35:31 +1000, <psycopg-request-IAPFreCvJWPBWskQ1e/[email protected]>  
wrote:

> Il giorno lun, 01/06/2009 alle 17.32 +0200, Federico Di Gregorio ha  
> scritto:
>> Il giorno mar, 02/06/2009 alle 01.10 +1000, Joel Nothman ha scritto:
>> > At first I had troubles with Python threads (none was available to
>> > make
>> > the call to connection.notice_handler). If I have understood the
>> > nature of
>> > the threading problem correctly, I solved these by replacing
>> > Py_BEGIN_ALLOW_THREADS with gstate = PyGILState_Ensure(), etc.
>>
>> Your patch makes psycopg lock other Python threads during the execution
>> of possibly slow libpq calls. PyGILState_XXX functions are supposed to
>> be used from C threads to acquire the GIL and allow the execution of
>> Python API calls (locking out other threads) but we don't need that
>> because the code is already executing as a Python thread.
> You probably just want to put PyGILState_XXX around the Python API call
> in the notice processor.

Thanks Frederico. Much appreciated. I found the API documentation quite  
unclear as to the role of PyGILState_XXX (but I haven't dealt much with  
concurrency handling in a few years). And so I wasn't sure whether it did  
one thing or its reverse!

Using Ensure only for the API call, the updated diff is attached.

- Joel

_______________________________________________
Psycopg mailing list
Psycopg-IAPFreCvJWPBWskQ1e/[email protected]
http://lists.initd.org/mailman/listinfo/psycopg
notice_handler.diff (application/octet-stream, 2.5 KB)
diff --git a/psycopg/connection.h b/psycopg/connection.h
index 701f46e..a0886ba 100644
--- a/psycopg/connection.h
+++ b/psycopg/connection.h
@@ -72,6 +72,7 @@ typedef struct {
     /* notice processing */
     PyObject *notice_list;
     PyObject *notice_filter;
+    PyObject *notice_handler; /* Optional callback */
     struct connectionObject_notice *notice_pending;
 
     /* notifies */
diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c
index 8b54bad..5aa4b35 100644
--- a/psycopg/connection_int.c
+++ b/psycopg/connection_int.c
@@ -58,6 +58,13 @@ conn_notice_callback(void *args, const char *message)
         notice->message = strdup(message);
         notice->next = self->notice_pending;
         self->notice_pending = notice;
+
+        if (self->notice_handler != Py_None) {
+			PyGILState_STATE gstate;
+			gstate = PyGILState_Ensure();
+            PyObject_CallFunction(self->notice_handler, "s", message);
+            PyGILState_Release(gstate);
+        }
     }
 }
 
diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c
index 4bba61c..cc31594 100644
--- a/psycopg/connection_type.c
+++ b/psycopg/connection_type.c
@@ -406,6 +406,7 @@ static struct PyMemberDef connectionObject_members[] = {
         "The current client encoding."},
     {"notices", T_OBJECT, offsetof(connectionObject, notice_list), RO},
     {"notifies", T_OBJECT, offsetof(connectionObject, notifies), RO},
+    {"notice_handler", T_OBJECT, offsetof(connectionObject, notice_handler), 0},
     {"dsn", T_STRING, offsetof(connectionObject, dsn), RO,
         "The current connection string."},
     {"status", T_INT,
@@ -469,6 +470,7 @@ connection_setup(connectionObject *self, const char *dsn)
     self->string_types = PyDict_New();
     self->binary_types = PyDict_New();
     self->notice_pending = NULL;
+    self->notice_handler = Py_None;
 
     pthread_mutex_init(&(self->lock), NULL);
 
@@ -512,6 +514,7 @@ connection_dealloc(PyObject* obj)
     Py_CLEAR(self->async_cursor);
     Py_CLEAR(self->notice_list);
     Py_CLEAR(self->notice_filter);
+    Py_CLEAR(self->notice_handler);
     Py_CLEAR(self->notifies);
     Py_CLEAR(self->string_types);
     Py_CLEAR(self->binary_types);
@@ -563,6 +566,7 @@ connection_traverse(connectionObject *self, visitproc visit, void *arg)
     Py_VISIT(self->async_cursor);
     Py_VISIT(self->notice_list);
     Py_VISIT(self->notice_filter);
+    Py_VISIT(self->notice_handler);
     Py_VISIT(self->notifies);
     Py_VISIT(self->string_types);
     Py_VISIT(self->binary_types);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.