Re: Async PQgetResult() question.

Поиск
Список
Период
Сортировка
От Matthew Hagerty
Тема Re: Async PQgetResult() question.
Дата
Msg-id 5.0.2.1.2.20010707131053.018fd5a0@pop.voyager.net
обсуждение исходный текст
Ответ на Re: Async PQgetResult() question.  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: Async PQgetResult() question.  (Tom Lane <tgl@sss.pgh.pa.us>)
Список 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@voyager.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



В списке pgsql-hackers по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: Async PQgetResult() question.
Следующее
От: Tom Lane
Дата:
Сообщение: Re: Async PQgetResult() question.