Cleanup of notice processing

The function is always called in the context of functions grabbing the
connection lock, so just use the same critical section instead of releasing
and re-acquiring it. It is not a problem as serious as the notifies process
(ticket #55) as the notices are a psycopg structure, not libpq. However the
change allows again processing notices/notifies in the same place,
which makes sense conceptually, plus we save some lock dance.
This commit is contained in:
Daniele Varrazzo 2011-06-04 01:49:03 +01:00
parent d9c0b8166f
commit 05659c0d16
2 changed files with 22 additions and 27 deletions

View File

@ -95,6 +95,10 @@ conn_notice_callback(void *args, const char *message)
self->notice_pending = notice; self->notice_pending = notice;
} }
/* Expose the notices received as Python objects.
*
* The function should be called with the connection lock and the GIL.
*/
void void
conn_notice_process(connectionObject *self) conn_notice_process(connectionObject *self)
{ {
@ -105,10 +109,6 @@ conn_notice_process(connectionObject *self)
return; return;
} }
Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock);
Py_BLOCK_THREADS;
notice = self->notice_pending; notice = self->notice_pending;
nnotices = PyList_GET_SIZE(self->notice_list); nnotices = PyList_GET_SIZE(self->notice_list);
@ -132,10 +132,6 @@ conn_notice_process(connectionObject *self)
0, nnotices - CONN_NOTICES_LIMIT); 0, nnotices - CONN_NOTICES_LIMIT);
} }
Py_UNBLOCK_THREADS;
pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS;
conn_notice_clean(self); conn_notice_clean(self);
} }
@ -143,8 +139,6 @@ void
conn_notice_clean(connectionObject *self) conn_notice_clean(connectionObject *self)
{ {
struct connectionObject_notice *tmp, *notice; struct connectionObject_notice *tmp, *notice;
Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock);
notice = self->notice_pending; notice = self->notice_pending;
@ -156,9 +150,6 @@ conn_notice_clean(connectionObject *self)
} }
self->notice_pending = NULL; self->notice_pending = NULL;
pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS;
} }

View File

@ -450,11 +450,13 @@ pq_commit(connectionObject *conn)
retvalue = pq_execute_command_locked(conn, "COMMIT", &pgres, &error, &_save); retvalue = pq_execute_command_locked(conn, "COMMIT", &pgres, &error, &_save);
Py_BLOCK_THREADS;
conn_notice_process(conn);
Py_UNBLOCK_THREADS;
pthread_mutex_unlock(&conn->lock); pthread_mutex_unlock(&conn->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
conn_notice_process(conn);
if (retvalue < 0) if (retvalue < 0)
pq_complete_error(conn, &pgres, &error); pq_complete_error(conn, &pgres, &error);
@ -512,11 +514,13 @@ pq_abort(connectionObject *conn)
retvalue = pq_abort_locked(conn, &pgres, &error, &_save); retvalue = pq_abort_locked(conn, &pgres, &error, &_save);
Py_BLOCK_THREADS;
conn_notice_process(conn);
Py_UNBLOCK_THREADS;
pthread_mutex_unlock(&conn->lock); pthread_mutex_unlock(&conn->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
conn_notice_process(conn);
if (retvalue < 0) if (retvalue < 0)
pq_complete_error(conn, &pgres, &error); pq_complete_error(conn, &pgres, &error);
@ -576,11 +580,13 @@ pq_reset(connectionObject *conn)
retvalue = pq_reset_locked(conn, &pgres, &error, &_save); retvalue = pq_reset_locked(conn, &pgres, &error, &_save);
Py_BLOCK_THREADS;
conn_notice_process(conn);
Py_UNBLOCK_THREADS;
pthread_mutex_unlock(&conn->lock); pthread_mutex_unlock(&conn->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
conn_notice_process(conn);
if (retvalue < 0) { if (retvalue < 0) {
pq_complete_error(conn, &pgres, &error); pq_complete_error(conn, &pgres, &error);
} }
@ -667,13 +673,12 @@ pq_is_busy(connectionObject *conn)
Py_BLOCK_THREADS; Py_BLOCK_THREADS;
conn_notifies_process(conn); conn_notifies_process(conn);
conn_notice_process(conn);
Py_UNBLOCK_THREADS; Py_UNBLOCK_THREADS;
pthread_mutex_unlock(&(conn->lock)); pthread_mutex_unlock(&(conn->lock));
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
conn_notice_process(conn);
return res; return res;
} }
@ -693,9 +698,9 @@ pq_is_busy_locked(connectionObject *conn)
return -1; return -1;
} }
/* We can't call conn_notice_process/conn_notifies_process because /* notices and notifies will be processed at the end of the loop we are in
they try to get the lock. We don't need anyway them because at the end of * (async reading) by pq_fetch. */
the loop we are in (async reading) pq_fetch will be called. */
return PQisBusy(conn->pgconn); return PQisBusy(conn->pgconn);
} }
@ -791,6 +796,7 @@ pq_execute(cursorObject *curs, const char *query, int async)
* (as in ticket #55). */ * (as in ticket #55). */
Py_BLOCK_THREADS; Py_BLOCK_THREADS;
conn_notifies_process(curs->conn); conn_notifies_process(curs->conn);
conn_notice_process(curs->conn);
Py_UNBLOCK_THREADS; Py_UNBLOCK_THREADS;
} }
@ -1380,8 +1386,6 @@ pq_fetch(cursorObject *curs)
break; break;
} }
conn_notice_process(curs->conn);
/* error checking, close the connection if necessary (some critical errors /* error checking, close the connection if necessary (some critical errors
are not really critical, like a COPY FROM error: if that's the case we are not really critical, like a COPY FROM error: if that's the case we
raise the exception but we avoid to close the connection) */ raise the exception but we avoid to close the connection) */