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);