Re: Async PQgetResult() question.

From: Matthew Hagerty <mhagerty(at)voyager(dot)net>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Async PQgetResult() question.
Date: 2001-07-07 17:40:57
Message-ID: 5.0.2.1.2.20010707131053.018fd5a0@pop.voyager.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Thanks for the response Tom! Does anyone ever tell you how much you are
appreciated? If not, I will. When I post to pgHackers I know I will get a
response (usually) from many knowledgeable people, and for that I thank
everyone. But I *always* receive a response from Tom, and for that I am
truly and greatly thankful!

Now, on with asynchronous query processing! WooHoo! :)

At 12:35 PM 7/7/2001 -0400, Tom Lane wrote:
>Matthew Hagerty <mhagerty(at)voyager(dot)net> writes:
> > I'm working with pqlib in asynchronous mode and I have a question about
> > PQgetResult. I have this situation:
>
> > submit a query via PQsendQuery()
> > flush to the backend with PQflush()
>
>I think the flush is not necessary; PQsendQuery should do it.

The docs warn that PQflush() must be called, here is what is says:

"PQflush needs to be called on a non-blocking connection before calling
select to determine if a response has arrived. If 0 is returned it ensures
that there is no data queued to the backend that has not actually been
sent. Only applications that have used PQsetnonblocking have a need for this."

Since I use PQsetnonblocking(), I included PQflush().

> > set my read descriptor on the socket and enter a select()
>
> > select returns read_ready on the socket, so call PGconsumeInput()
> > PQisBusy() returns zero, so call PQgetResult()
> > PQgetResult() returns a pointer so do whatever with the result
> > call PQclear() on the result
>
>So far so good.
>
> > Now what do I do?
>
>Loop back to the PQisBusy() step. In practice, you are probably doing
>this in an event-driven application, and the select() is the place in
>the outer loop that blocks for an event. PQconsumeInput followed by
>a PQisBusy/PQgetResult/process result loop are just your response
>subroutine for an input-ready-on-the-database-connection event.

This is my primary concern. I'm actually writing a server and I have other
events going on. I wrote a small test program and at this point (after
reading the first result) I looped back to my select, but the socket never
went read-ready again, so the last
PQconsumeInput()/PQisBusy()/PQgetResults() was never called to receive the
NULL response from PQgetResult(), which is how the docs say I know the
query is done.

But if I loop back to PQconsumeInput()/PQisBusy(), then I am effectively
blocking since I have no way to know that PQconsumeInput() won't block or
that the PQisBusy() will ever return zero again.

If there is more input to read, i.e. the NULL from PQgetResult(), then how
come the socket never goes read-ready again, as in my test program
above? Or can I call PQconsumeInput() repeatedly and be guaranteed that it
will not block and that I will be able to process the remaining results?

> > The docs say that in async mode that PQgetResult() must
> > be called until it returns NULL. But, how do I know that calling
> > PQgetResult() a second, third, fourth, etc. time will not block?
>
>When PQisBusy says you can.
>
> > When
> > PQisBusy() returns zero, does that mean that PQgetResult() is guaranteed
> > not to block for all results, i.e. until it returns NULL and a new
> query is
> > issued?
>
>No, it means *one* result is available (or that a NULL is available, ie,
>libpq has detected the end of the query cycle). Its answer will
>probably change after you read the result.

My main problem is that sockets are slow devices and I have some other disk
I/O I have to be doing as well. I know that another call to PQgetResult()
will probably return NULL, but if that data has not come from the backend
yet then PQgetResult() will block, and I can't sit in a loop calling
PQconsumeInput()/PQisBusy() becuse that is just like blocking and I may as
well just let PQgetResult() block.

It seems that when the query cycle has ended and PQgetResult() would return
NULL, the socket should be set read-ready again, but that never
happens... Well, at least I did not see it happen. I can send my test
code if need be.

Thanks,
Matthew

> regards, tom lane
>
>---------------------------(end of broadcast)---------------------------
>TIP 6: Have you searched our list archives?
>
>http://www.postgresql.org/search.mpl

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message David Bennett 2001-07-07 18:02:55 RE: New SQL Datatype RECURRINGCHAR
Previous Message Tom Lane 2001-07-07 16:35:59 Re: Async PQgetResult() question.