mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-12 07:10:33 +03:00
Functions to poll in ready state moved on the connection.
This commit is contained in:
parent
9f5d835de6
commit
d915cb12a8
|
@ -135,6 +135,8 @@ HIDDEN int conn_set_client_encoding(connectionObject *self, const char *enc);
|
||||||
HIDDEN PyObject *conn_poll_connect_send(connectionObject *self);
|
HIDDEN PyObject *conn_poll_connect_send(connectionObject *self);
|
||||||
HIDDEN PyObject *conn_poll_connect_fetch(connectionObject *self);
|
HIDDEN PyObject *conn_poll_connect_fetch(connectionObject *self);
|
||||||
HIDDEN PyObject *conn_poll_ready(connectionObject *self);
|
HIDDEN PyObject *conn_poll_ready(connectionObject *self);
|
||||||
|
HIDDEN PyObject *conn_poll_send(connectionObject *self);
|
||||||
|
HIDDEN PyObject *conn_poll_fetch(connectionObject *self);
|
||||||
HIDDEN PyObject *conn_poll_green(connectionObject *self);
|
HIDDEN PyObject *conn_poll_green(connectionObject *self);
|
||||||
|
|
||||||
/* exception-raising macros */
|
/* exception-raising macros */
|
||||||
|
|
|
@ -649,13 +649,13 @@ conn_poll_ready(connectionObject *self)
|
||||||
/* if there is an asynchronous query underway, poll it */
|
/* if there is an asynchronous query underway, poll it */
|
||||||
if (self->async_cursor != NULL) {
|
if (self->async_cursor != NULL) {
|
||||||
if (self->async_status == ASYNC_WRITE) {
|
if (self->async_status == ASYNC_WRITE) {
|
||||||
return curs_poll_send((cursorObject *) self->async_cursor);
|
return conn_poll_send(self);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* this gets called both for ASYNC_READ and ASYNC_DONE, because
|
/* this gets called both for ASYNC_READ and ASYNC_DONE, because
|
||||||
even if the async query is complete, we still might want to
|
even if the async query is complete, we still might want to
|
||||||
check for NOTIFYs */
|
check for NOTIFYs */
|
||||||
return curs_poll_fetch((cursorObject *) self->async_cursor);
|
return conn_poll_fetch(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,6 +677,86 @@ conn_poll_ready(connectionObject *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* conn_poll_send - poll the connection when flushing data to the backend */
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
conn_poll_send(connectionObject *self)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* flush queued output to the server */
|
||||||
|
res = pq_flush(self);
|
||||||
|
|
||||||
|
if (res == 1) {
|
||||||
|
/* some data still waiting to be flushed */
|
||||||
|
Dprintf("conn_poll_send: returning %d", PSYCO_POLL_WRITE);
|
||||||
|
return PyInt_FromLong(PSYCO_POLL_WRITE);
|
||||||
|
}
|
||||||
|
else if (res == 0) {
|
||||||
|
/* all data flushed, start waiting for results */
|
||||||
|
Dprintf("conn_poll_send: returning %d", PSYCO_POLL_READ);
|
||||||
|
self->async_status = ASYNC_READ;
|
||||||
|
return PyInt_FromLong(PSYCO_POLL_READ);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* unexpected result */
|
||||||
|
PyErr_SetString(OperationalError, PQerrorMessage(self->pgconn));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* conn_poll_fetch - poll the connection when reading results from the backend
|
||||||
|
*
|
||||||
|
* Assume self->async_cursor is not null: use such cursor to store results.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
conn_poll_fetch(connectionObject *self)
|
||||||
|
{
|
||||||
|
int is_busy;
|
||||||
|
int last_result;
|
||||||
|
|
||||||
|
/* consume the input */
|
||||||
|
is_busy = pq_is_busy(self);
|
||||||
|
if (is_busy == -1) {
|
||||||
|
/* there was an error, raise the exception */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (is_busy == 1) {
|
||||||
|
/* the connection is busy, tell the user to wait more */
|
||||||
|
Dprintf("conn_poll_fetch: returning %d", PSYCO_POLL_READ);
|
||||||
|
return PyInt_FromLong(PSYCO_POLL_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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->async_status == ASYNC_READ)
|
||||||
|
last_result = curs_get_last_result((cursorObject *)self->async_cursor);
|
||||||
|
else
|
||||||
|
last_result = 0;
|
||||||
|
|
||||||
|
if (last_result == 0) {
|
||||||
|
Dprintf("conn_poll_fetch: returning %d", PSYCO_POLL_OK);
|
||||||
|
/* self->async_status cannot be ASYNC_WRITE here, because we
|
||||||
|
never execute curs_poll_fetch in ASYNC_WRITE state, so we can
|
||||||
|
safely set it to ASYNC_DONE because we either fetched the result or
|
||||||
|
there is no result to fetch */
|
||||||
|
self->async_status = ASYNC_DONE;
|
||||||
|
return PyInt_FromLong(PSYCO_POLL_OK);
|
||||||
|
}
|
||||||
|
else if (last_result == 1) {
|
||||||
|
Dprintf("conn_poll_fetch: got result, but data remaining, "
|
||||||
|
"returning %d", PSYCO_POLL_READ);
|
||||||
|
return PyInt_FromLong(PSYCO_POLL_READ);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* conn_poll_green - poll a *sync* connection with external wait */
|
/* conn_poll_green - poll a *sync* connection with external wait */
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
|
@ -86,8 +86,6 @@ typedef struct {
|
||||||
/* C-callable functions in cursor_int.c and cursor_ext.c */
|
/* C-callable functions in cursor_int.c and cursor_ext.c */
|
||||||
HIDDEN void curs_reset(cursorObject *self);
|
HIDDEN void curs_reset(cursorObject *self);
|
||||||
HIDDEN int curs_get_last_result(cursorObject *self);
|
HIDDEN int curs_get_last_result(cursorObject *self);
|
||||||
HIDDEN PyObject *curs_poll_send(cursorObject *self);
|
|
||||||
HIDDEN PyObject *curs_poll_fetch(cursorObject *self);
|
|
||||||
|
|
||||||
/* exception-raising macros */
|
/* exception-raising macros */
|
||||||
#define EXC_IF_CURS_CLOSED(self) \
|
#define EXC_IF_CURS_CLOSED(self) \
|
||||||
|
|
|
@ -96,79 +96,3 @@ curs_get_last_result(cursorObject *self) {
|
||||||
return pq_fetch(self) == -1 ? -1 : 0;
|
return pq_fetch(self) == -1 ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* curs_poll_send - handle cursor polling when flushing output */
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
curs_poll_send(cursorObject *self)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
/* flush queued output to the server */
|
|
||||||
res = pq_flush(self->conn);
|
|
||||||
|
|
||||||
if (res == 1) {
|
|
||||||
/* some data still waiting to be flushed */
|
|
||||||
Dprintf("cur_poll_send: returning %d", PSYCO_POLL_WRITE);
|
|
||||||
return PyInt_FromLong(PSYCO_POLL_WRITE);
|
|
||||||
}
|
|
||||||
else if (res == 0) {
|
|
||||||
/* all data flushed, start waiting for results */
|
|
||||||
Dprintf("cur_poll_send: returning %d", PSYCO_POLL_READ);
|
|
||||||
self->conn->async_status = ASYNC_READ;
|
|
||||||
return PyInt_FromLong(PSYCO_POLL_READ);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* unexpected result */
|
|
||||||
PyErr_SetString(OperationalError, PQerrorMessage(self->conn->pgconn));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* curs_poll_fetch - handle cursor polling when reading result */
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
curs_poll_fetch(cursorObject *self)
|
|
||||||
{
|
|
||||||
int is_busy;
|
|
||||||
int last_result;
|
|
||||||
|
|
||||||
/* consume the input */
|
|
||||||
is_busy = pq_is_busy(self->conn);
|
|
||||||
if (is_busy == -1) {
|
|
||||||
/* there was an error, raise the exception */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else if (is_busy == 1) {
|
|
||||||
/* the connection is busy, tell the user to wait more */
|
|
||||||
Dprintf("cur_poll_fetch: returning %d", PSYCO_POLL_READ);
|
|
||||||
return PyInt_FromLong(PSYCO_POLL_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
/* self->conn->async_status cannot be ASYNC_WRITE here, because we
|
|
||||||
never execute curs_poll_fetch in ASYNC_WRITE state, so we can
|
|
||||||
safely set it to ASYNC_DONE because we either fetched the result or
|
|
||||||
there is no result to fetch */
|
|
||||||
self->conn->async_status = ASYNC_DONE;
|
|
||||||
return PyInt_FromLong(PSYCO_POLL_OK);
|
|
||||||
}
|
|
||||||
else if (last_result == 1) {
|
|
||||||
Dprintf("cur_poll_fetch: got result, but data remaining, "
|
|
||||||
"returning %d", PSYCO_POLL_READ);
|
|
||||||
return PyInt_FromLong(PSYCO_POLL_READ);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user