[ 
https://issues.apache.org/jira/browse/QPID-8538?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17360736#comment-17360736
 ] 

Robbie Gemmell commented on QPID-8538:
--------------------------------------

The AMQP spec doesnt define when you should replenish credit as it really has 
nothing to do with the spec. The spec provides the mechanism, and its up to the 
peers how and when to use it.

It seems like in this case the client returns a message as soon as the first 
arrives after it starts draining, rather than awaiting the drain completing, 
but only grants new credit after the drain completes and the last resulting 
message is fetched. This actually makes sense as it could/would lose track of 
the draining process and get itself very confused later if it granted fresh 
credit at that point otherwise. It could be written to behave in a completely 
different way (awaiting drain completion before returning anything) to let it 
do just that, but as I said I think it unlikely it will change any time soon; 
feel free to observe the activity around qpid-cpp in recent years and judge for 
yourself.

Around what the drained method does, the documentation doesnt look wrong, you 
are likely just looking in the wrong place and/or not understanding it. Which 
is fair, its a pretty complicated protocol, and proton adds its own unique 
complexities on top, especially with its upper/lower layer separation. The code 
you quote will be from the 'transport' layer at the bottom, dealing with the 
individual protocol frames, while the API call you reference is from the 
'engine' layer on top that knows little of these. Protons API considered 
'drained' credits to be those discarded when advancing the delivery-count 
without sending messages.

The 'delivery-count' value is part-count (which I would guess is probably how 
it came to have that name originally) but also part-other. Its more of a 
sequence number. When a drain occurs and some unused credit is discarded, 
delivery-count is advanced without any deliveries taking place. It also can 
start at arbitrary points. So you could have a delivery-count that exactly 
matches the number of deliveries recived, or one that bears no relation at all 
to the number of deliveries actually received, hence the 'not a count' 
description. (I dont know why it wasnt renamed, since the name is conceptual 
only, it never goes on the wire).

 

This will be my last reply here. I was mainly doing a courtesy of actually 
giving you some response, rather than probable no-reply otherwise, to outline 
some misunderstandings, note the chances of qpid-cpp changing at this point, 
and suggest alternatives to avoiding the draining if it bothers you, such as 
using the get method or better just using Proton C++.

> Receiver fetch method depletes credit and slows down receiver
> -------------------------------------------------------------
>
>                 Key: QPID-8538
>                 URL: https://issues.apache.org/jira/browse/QPID-8538
>             Project: Qpid
>          Issue Type: Bug
>          Components: C++ Client
>    Affects Versions: qpid-cpp-1.39.0
>            Reporter: Peter Moran
>            Priority: Major
>
> As remote broker java broker is used.
> e.g 
>  capacity of link is 10
>  credit is 10
> When calling Method ConnectionContext::fetch and there are no data available 
> inside receiver (get returns false) it
>  # Enables drain mode  pn_link_drain(lnk->receiver, 0);
>  # Tries to process all queued messages (while 
> (pn_link_draining(lnk->receiver) && !pn_link_queued(lnk->receiver)))
>  # Credit is being drained by broker pn_do_flow in proton ( pn_sequence_t 
> delta = delivery_count - link->state.delivery_count;) -> delta is 10 and 
> credit is cleared to 0, yet no messages arrived from broker at all
>  if there are queued messages and credit is 0 then pn_link_draining returns 
> false and while stops
>  # however if (lnk->capacity && pn_link_queued(lnk->receiver) == 0) replenish 
> credit only if there are no outstanding queued messages to the maximum 
> capacity, this should be rather capacity - credit, but also the condition 
> seems to be wrong, it should not check the queued messages.
> the code should look like this
> {code:java}
> if (lnk->capacity) {
>     pn_link_flow(lnk->receiver, lnk->capacity - 
> pn_link_credit(lnk->receiver));
> }
> or
> if (lnk->capacity) { 
> pn_link_flow(lnk->receiver, pn_link_drained(lnk->receiver));
> }{code}
> this would much more look like what is inside proton c++ api
> {code:java}
> void credit_topup(pn_link_t *link) {
>     assert(pn_link_is_receiver(link));
>     int window = link_context::get(link).credit_window;
>     if (window) {
>         int delta = window - pn_link_credit(link);
>         pn_link_flow(link, delta);
>     }
> }
>       // receiver
>             if (!pn_link_credit(lnk) && lctx.draining) {
>                 lctx.draining = false;
>                 pn_link_set_drain(lnk, false);
>                 receiver r(make_wrapper<receiver>(lnk));
>                 handler.on_receiver_drain_finish(r);
>             }
>             credit_topup(lnk);
> {code}
> there is no condition about queued and also the resulting credit is set to 
> the link capacity 
>  (e.g 10 - delta) delta is delivery count reduced from by pn_do_flow,
> However this to me looks like some incompatibility between client and broker, 
> as one would not expect that delta is 10 if no messages are received from 
> broker. is this some kind of message sequencing problem?
>  
> fyi pn_link_queued messages does not mean they they are locally available 
> they might be still on broker and also getAvaialable implementation is wrong.
>  
>  
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to