From c1a24f4ca279f8057f9f7a3fe06e9c8a5b1dc818 Mon Sep 17 00:00:00 2001 From: Federico Di Gregorio Date: Mon, 5 Apr 2010 16:52:25 +0200 Subject: [PATCH] NOTIFYs fix and poll status changes POLL_OK has been changed from 3 to 0 to let the user specify a short loop just as "if not curs.poll()" instead of having to check for write and read separately. For an example of this, see examples/notify.py. --- ChangeLog | 6 ++++++ examples/notify.py | 2 +- lib/extensions.py | 4 ++-- psycopg/connection.h | 5 ++--- psycopg/cursor.h | 6 +++--- psycopg/cursor_int.c | 13 ++++++++++--- psycopg/cursor_type.c | 7 +------ 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index b355bd52..20af4407 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-04-05 Federico Di Gregorio + + * Fixed problem with asynchronous NOTIFYs. + + * Integrated async pacthes from Jan's git tree. + 2010-03-13 Federico Di Gregorio * Release 2.0.14. diff --git a/examples/notify.py b/examples/notify.py index b5a613d2..c88098a8 100644 --- a/examples/notify.py +++ b/examples/notify.py @@ -39,5 +39,5 @@ while 1: if select.select([curs],[],[],5)==([],[],[]): print "Timeout" else: - if curs.isready(): + if not curs.poll(): print "Got NOTIFY: %s" % str(curs.connection.notifies.pop()) diff --git a/lib/extensions.py b/lib/extensions.py index 64ea7cb8..edffee9c 100644 --- a/lib/extensions.py +++ b/lib/extensions.py @@ -76,10 +76,10 @@ STATUS_ASYNC = 4 # This is a usefull mnemonic to check if the connection is in a transaction STATUS_IN_TRANSACTION = STATUS_BEGIN -"""psycopg async connection polling values""" +"""psycopg asynchronous connection polling values""" +POLL_OK = 0 POLL_READ = 1 POLL_WRITE = 2 -POLL_OK = 3 """Backend transaction status values.""" TRANSACTION_STATUS_IDLE = 0 diff --git a/psycopg/connection.h b/psycopg/connection.h index c0fec18e..ec8e8691 100644 --- a/psycopg/connection.h +++ b/psycopg/connection.h @@ -53,11 +53,10 @@ extern "C" { #define ASYNC_READ 1 #define ASYNC_WRITE 2 -/* polling result, try to keep in sync with PostgresPollingStatusType from - libpq-fe.h */ +/* polling result */ +#define PSYCO_POLL_OK 0 #define PSYCO_POLL_READ 1 #define PSYCO_POLL_WRITE 2 -#define PSYCO_POLL_OK 3 /* Hard limit on the notices stored by the Python connection */ #define CONN_NOTICES_LIMIT 50 diff --git a/psycopg/cursor.h b/psycopg/cursor.h index bbe80ea9..a0a3a822 100644 --- a/psycopg/cursor.h +++ b/psycopg/cursor.h @@ -62,10 +62,10 @@ typedef struct { PyObject *pgstatus; /* last message from the server after an execute */ Oid lastoid; /* last oid from an insert or InvalidOid */ - PyObject *casts; /* an array (tuple) of typecast functions */ - PyObject *caster; /* the current typecaster object */ + PyObject *casts; /* an array (tuple) of typecast functions */ + PyObject *caster; /* the current typecaster object */ - PyObject *copyfile; /* file-like used during COPY TO/FROM ops */ + PyObject *copyfile; /* file-like used during COPY TO/FROM ops */ Py_ssize_t copysize; /* size of the copy buffer during COPY TO/FROM ops */ #define DEFAULT_COPYSIZE 16384 #define DEFAULT_COPYBUFF 8132 diff --git a/psycopg/cursor_int.c b/psycopg/cursor_int.c index 4a63f0c1..11472843 100644 --- a/psycopg/cursor_int.c +++ b/psycopg/cursor_int.c @@ -141,9 +141,16 @@ curs_poll_fetch(cursorObject *self) return PyInt_FromLong(PSYCO_POLL_READ); } - /* data has arrived, try to fetch all of it or, if it failed, tell the - user to wait more */ - last_result = curs_get_last_result(self); + /* try to fetch the data only if this was a poll following a read + request; else just return POLL_OK to the user: this is necessary + because of asynchronous NOTIFYs that can be sent by the backend + even if the user didn't asked for them */ + + if (self->conn->async_status == ASYNC_READ) + last_result = curs_get_last_result(self); + else + last_result = 0; + if (last_result == 0) { Dprintf("cur_poll_fetch: returning %d", PSYCO_POLL_OK); return PyInt_FromLong(PSYCO_POLL_OK); diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index 73217c25..895b3cec 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -1485,14 +1485,9 @@ psyco_curs_poll(cursorObject *self) if (self->conn->async_status == ASYNC_WRITE) { return curs_poll_send(self); } - else if (self->conn->async_status == ASYNC_READ) { + else { return curs_poll_fetch(self); } - else { - PyErr_Format(OperationalError, "unexpected execution status: %d", - self->conn->async_status); - return NULL; - } } /* extension: closed - return true if cursor is closed*/