Re: libpq ASYNC with PQgetResult and PQisBusy

From: Raimon Fernandez <coder(at)montx(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-general List <pgsql-general(at)postgresql(dot)org>
Subject: Re: libpq ASYNC with PQgetResult and PQisBusy
Date: 2010-12-20 20:49:35
Message-ID: 2C5CFB1E-FAAA-4CFD-A7F2-1DFBCD194010@montx.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general


On 20dic, 2010, at 18:48 , Tom Lane wrote:

>> So, now I'm using the PQisBusy to check if postgre is still busy and I can safely call the PQgetResult wihtout blocking, or just wait *some time* before sending a new PQisBusy.
>
> Your proposed code is still a busy-wait loop.

This is how are made all the examples I've found.

Last year I was implementing the FE/BE protocol v3 and there I was using what you proposed, a TCP/Socket with events, no loops and no waits, just events.

> What you should be doing is waiting for some data to arrive on the socket.

where I have to wait, in a function inside my plugin or from the framework that uses my plugin ?

> Once you see
> read-ready on the socket, call PQconsumeInput, then check PQisBusy to
> see if the query is complete or not. If not, go back to waiting on the
> socket. Typically you'd use select() or poll() to watch for both data
> on libpq's socket and whatever other events your app is interested in.

Here is what I've found:

extern int PQsocket(const PGconn *conn);

There are some examples in the postgreSQL documentation:

/*
* Sleep untilsomething happens on the connection. We use select(2)
* to wait for input, but you could also use poll() or similar
* facilities.
*/


int sock;
fd_set input_mask;

sock = PQsocket(conn);

if (sock < 0) break; /* shouldn’t happen */

FD_ZERO(&input_mask);
FD_SET(sock, &input_mask);

if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) {

fprintf(stderr, "select() failed: %s\n", strerror(errno));
exit_nicely(conn);
}

/* Now check for input */
PQconsumeInput(conn);

while ((notify = PQnotifies(conn)) != NULL) {

fprintf(stderr, "ASYNC NOTIFY of ’%s’ received from backend pid %d\n", notify->relname, notify->be_pid);
PQfreemem(notify);
}

The select(2) that says that are using for wait is this line ? if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) {

I can't see where is 'sleeping'

and the approach you are refering, is the only way to non-block the plugin calls and postgreSQL ?

>> here is my montxPG_isBusy
>
>> static long montxPG_isBusy()
>
>> { int execStatus;
>> int consumeeVar;
>
>> consumeeVar = PQconsumeInput(gPGconn);
>
>> if (consumeeVar == 0) return (long) PGRES_FATAL_ERROR;
>
>> execStatus = PQisBusy(gPGconn);
>
>> return (long) execStatus;
>
>> }
>
> This code seems a bit confused. PQisBusy returns a bool (1/0), not a
> value of ExecStatusType.

yes, here the execStatus is the name of the int, and yes, I know, a bad name ...

thanks again,

regards,

r.

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Kenneth Buckler 2010-12-20 21:05:15 Re: PostgreSQL Trusted Startup
Previous Message Scott Marlowe 2010-12-20 20:48:25 Re: PostgreSQL Trusted Startup