Hi Frase

----- Original Message -----
> From: "Fraser Adams" <[email protected]>
> To: [email protected]
> Sent: Wednesday, November 20, 2013 3:28:48 PM
> Subject: Re: using proton messenger *asynchronously*
> 
> Thanks for this (and your other mail) Ken that's *really* useful - glad
> I wasn't totally on the wrong track. I did (eventually) figure out the
> "pn_messenger_recv(messenger, 1);" stuff myself - which is when my crazy
> JavaScript stuff started working :-D
> 
> I really wish that there were more docs - the header/DOxygen stuff is OK
> and it makes sense I'm sure to those familiar with the code base, but I
> tend to find "example usage" more helpful than abstract docs - I've
> largely got *no idea* how I'd would work out how to use engine, I'd
> probably end up "reverse engineering" it from messenger and/or
> qpid::messaging, which is less than ideal.
>

You raise a very good point - I think most (all?) of the examples and user 
documentation is Messenger based.  If you're interested in working directly 
with the engine, sadly, there isn't much out there.  I _used_ to have a couple 
of simple clients/server examples back in the pre 0.3 days that worked against 
the engine API directly [1] - but that's way, way out of date.  I think the 
best approach would be as you suggest - try to figure out how Messenger uses 
engine.  The other example would be Ted's dispatch code.

We really need a how-to guide to the engine interface, or some very brain dead 
simple send/recv examples in the top-level example directory.
 
> On a somewhat related aside, I'd have killed for some code comments at
> the weekend fighting my way through this. It seems to be pretty much
> universal across Proton and Qpid that there are next to no comments
> aside from the API DOxygen. I realise that some may argue that comments
> can get stale and out of date comments might be misleading, but if I'm
> honest I found working my way through without comments a pretty
> frustrating experience. Maybe it's just me?
> 

It is definitely not you - I'm constantly finding myself flummoxed, most often 
by the proton C code.  Personally, I find the function naming far too terse, 
and that makes the intent of the code hard to understand at times.  As I'm 
working on the code, I'll add comments to areas of the code that take me more 
than three re-reads to figure out.  I encourage you and others to do the same.  
And if a chunk of code is especially obfuscated, don't hesitate to ask the 
author to clarify it. 

> Cheers,
> Frase
> 
> 

[1] 
http://svn.apache.org/viewvc/qpid/proton/branches/0.3/proton-c/examples/mailbox/



> On 19/11/13 20:30, Ken Giusti wrote:
> > Hit "send" a bit too quickly:
> >
> > The "official" proton docs are linked from the proton release web page:
> >
> > http://qpid.apache.org/releases/qpid-proton-0.5/index.html
> >
> >
> > These are generated from the header file - we're missing an overview page
> > though (https://issues.apache.org/jira/browse/PROTON-462)
> >
> > Justin - can you remove those old proton api docs Fraser hit from our web
> > site?
> >
> >>> http://qpid.apache.org/components/messenger/book/sending-and-receiving.html
> > thanks,
> >
> > -K
> >
> >
> > ----- Original Message -----
> >> From: "Ken Giusti" <[email protected]>
> >> To: [email protected]
> >> Sent: Tuesday, November 19, 2013 3:17:37 PM
> >> Subject: Re: using proton messenger *asynchronously*
> >>
> >> Hi Fraser,
> >>
> >> ----- Original Message -----
> >>> From: "Fraser Adams" <[email protected]>
> >>> To: [email protected]
> >>> Sent: Sunday, November 17, 2013 7:04:53 AM
> >>> Subject: using proton messenger *asynchronously*
> >>>
> >>> Hey all,
> >>> I've been messing around trying to get messenger to do something in
> >>> asynchronous mode. The comments here:
> >>> http://qpid.apache.org/components/messenger/book/sending-and-receiving.html
> >>>
> >>> Suggest that it's possible - though the doc there probably needs an edit
> >>> because |pn_messenger_send(messenger) |isn't legal - it needs a second
> >>> parameter, the actual prototype is:
> >>> /*
> >>>    * @param[in] messenger the messager
> >>>    * @param[in] n the number of messages to send
> >>>    *
> >>>    * @return an error code or zero on success
> >>>    * @see error.h
> >>>    */
> >>> PN_EXTERN int pn_messenger_send(pn_messenger_t *messenger, int n);
> >>>
> >>> But that's by the by:
> >>>
> >>>
> >>> When I started playing with this I eventually figured out that I needed
> >>> to have:
> >>> pn_messenger_set_blocking(messenger, false);
> >>>
> >>> After I've created a messenger, as well as doing:
> >>> pn_messenger_send(messenger, 0);
> >>>
> >>>
> >>> But it all seems a lot more cryptic than that. Under the hood there's a
> >>> call to pn_messenger_tsync, which in blocking mode eventually ends up
> >>> blocking on a poll and has a while loop internally. Now that tsync call
> >>> seems to do a whole bunch of things actually leading to sends and
> >>> receives of the sockets, so it seems just calling pn_messenger_send in
> >>> non-blocking mode isn't enough and I need to call
> >>> pn_messenger_work(messenger, 0); too.
> >>>
> >> You're correct here - it appears that the web page you reference hasn't
> >> been
> >> updated since Rafi added the non-blocking stuff.  You definitely need to
> >> call pn_messenger_work() in order to have data hit the wire.
> >>
> >>> I've attached some *really hacky* code. The code is pretty rubbishy, in
> >>> the case of send it's calling pn_messenger_send then calling a main loop
> >>> that does pn_messenger_work(messenger, 0); periodically. The select to
> >>> sleep every second is a massive hack, and I've tried different values of
> >>> sleep - ultimately I'd want it to be a proper asynchronous application.
> >>>
> >>>
> >>> As far as I can see using the send and recv I've attached things get as
> >>> far as completing the AMQP negotiation, but the actual message isn't
> >>> being sent and it *looks like* something to do with credit.
> >>>
> >>> I've hacked around in proton "instrumenting" it - OK I've added a bunch
> >>> of printfs :-)
> >>>
> >>> Hands up who knows that code best? fancy volunteering to document the
> >>> call graph, trying to work my way around that made my *head explode* ;-D
> >>> I'm sure it's easy when you know, but trying to figure the path of the
> >>> actual message.........
> >>>
> >>>
> >>> I *think* that there's some sort of "store" where pn_messenger_put
> >>> actually puts the message and at some point the message should be
> >>> retrieved from there by the transport.
> >>>
> >>> Looking through transport.c I've added printfs to
> >>> "pn_output_write_amqp_header" and "pn_output_write_amqp" and can see
> >>> those getting called and pn_process(transport) seems to be getting
> >>> called too.
> >>>
> >>> Looking at where I'm at; the message is being put into the store
> >>>
> >>> pn_messenger_put
> >>> calling pn_buffer_append 93
> >>> 0 83 112 -48 0 0 0 11 0 0 0 5 66 80 4 64 66 82 0 0 83 115 -48 0 0 0 49 0
> >>> 0 0 13 64 64 -95 14 97 109 113 112 58 47 47 48 46 48 46 48 46 48 64 64
> >>> 64 64 64 -125 0 0 0 0 0 0 0 0 -125 0 0 0 0 0 0 0 0 64 82 0 64 0 83 119
> >>> -95 12 72 101 108 108 111 32 87 111 114 108 100 33
> >>>
> >>> So that's the "Hello World!" at the end of the buffer :-) but when I
> >>> print out the values needed for the test in pn_process_tpwork_sender I
> >>> keep getting:
> >>>
> >>> pn_process_tpwork_sender state->sent = 0 delivery->done = 1 93
> >>> ssn_state->remote_incoming_window = 0
> >>> link_state->link_credit = 0
> >>>
> >>>
> >>> This *seems* to be saying that the message is still in the store but
> >>> remote_incoming_window and link_credit are zero. That basically prints
> >>> out every time I call pn_messenger_work(messenger, 0);
> >>>
> >>>
> >>> There's clearly something I'm missing? There wasn't anything in the
> >>> synchronous send/recv that explicitly set credits though? I've spent
> >>> most of the weekend tearing my hair out on this, so I'd be grateful for
> >>> any ideas.
> >>>
> >> You're correct - it does come down to credit.  In your recv.c code, the
> >> main_loop needs to supply a credit count to the pn_messenger_recv() call:
> >>
> >>      // XXX pn_messenger_recv(messenger, 0);
> >>      pn_messenger_recv(messenger, 1);
> >>
> >> This will cause the receiver to send a "flow" frame.
> >>
> >> All in all, your code is pretty close - I've made a few tweaks (attached).
> >> I
> >> think the big difference is the call to pn_messenger_work() on the sender
> >> -
> >> you need to call that until the outgoing message has been sent
> >> (pn_messenger_outgoing() == 0).
> >>
> >> And from what I can tell - again, not documented - you need to keep
> >> calling
> >> pn_messenger_work() until it returns a non-zero value.  This is
> >> inconsistent
> >> with the Java variant (which returns 0 when there's no more work to do) -
> >> I've got a proposed fix pending
> >> (https://reviews.apache.org/r/15458/diff/#5)
> >> for 0.6.
> >>
> >> As you've noticed the docs tend to not keep up with the code changes, and
> >> that makes things difficult to understand.  Usually the header files are
> >> more up to date.  Personally, I've learned most from reading the python
> >> unit
> >> tests (tests/python/proton_tests/*).
> >>
> >>> I was serious about the call graph documentation BTW, being pretty new
> >>> to the code base it was pretty daunting following the various levels of
> >>> indirection and I'm still nowhere near actually understanding how it
> >>> works, how do you guys find your way around when it comes to debugging -
> >>> is it just experience or are you using other debug tools?
> >>>
> >>> Cheers,
> >>> Frase
> >>>
> >>
> >> BTW, if you set an environment variable called "PN_TRACE_FRM" to one:
> >>
> >> $ export PN_TRACE_FRM=1
> >>
> >> proton will dump a trace of the traffic "on the wire" when you run your
> >> programs.  Doing that, I could see that the code was getting "stuck" at
> >> the
> >> point where I would think recv should issue a flow frame.
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: [email protected]
> >>> For additional commands, e-mail: [email protected]
> >> --
> >> -K
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: [email protected]
> >> For additional commands, e-mail: [email protected]
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
> 
> 

-- 
-K

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

Reply via email to