On 20 July 2017 at 05:18, Kenton Varda <[email protected]> wrote:
> On Wed, Jul 19, 2017 at 2:57 PM, Ross Light <[email protected]> wrote:
>> On Wed, Jul 19, 2017 at 1:46 PM Thomas Leonard <[email protected]> wrote:

[ thanks for the replies - snipping the bits I now understand ]

>>> Can takeFromOtherQuestion be used more than once for a single source
>>> question?
>>
>> I would assume that it could be used until Finish message is sent for that
>> question, much like other question-based data.  In practice, every call's
>> result is held in the answers table until Finish is received.
>
> No, it can only be used once.
>
> For languages without garbage collection, it would be annoying for the
> protocol to specify that some messages can potentially be shared.

I thought that must be the reason originally, but it seems that
takeFromOtherQuestion requires sharing even if it can only be used
once, because the struct is held by the original answer (for
pipelining) and also by the question that took it.

>>> [Return.releaseParamCaps]
>>> > If true, all capabilities that were in the params should be considered
>>> > released.
>>>
>>> Just to be sure: as if the sender had sent a release message for each one
>>> with `count=1`?
>>
>> (I might be wrong on this point, it's been a while since I've looked.  The
>> docs should probably spell this out.)  Usually.  The list of CapDescriptors
>> in a Payload could point to the same capability multiple times.  A release
>> message of count=1 per CapDescriptor is a more accurate way of phrasing
>> this.

Good point (and that is what my implementation does).

>>> [Disembargo]
>>> > Embargos are used to enforce E-order in the presence of promise
>>> > resolution.  That is, if an
>>> > application makes two calls foo() and bar() on the same capability
>>> > reference, in that order,
>>> > the calls should be delivered in the order in which they were made.
>>> > But if foo() is called
>>> > on a promise, and that promise happens to resolve before bar() is
>>> > called, then the two calls
>>> > may travel different paths over the network, and thus could arrive in
>>> > the wrong order.  In
>>> > this case, the call to `bar()` must be embargoed, and a `Disembargo`
>>> > message must be sent along
>>> > the same path as `foo()` to ensure that the `Disembargo` arrives after
>>> > `foo()`.
>>>
>>> What does "this case" refer to? When exactly is an embargo needed, and
>>> when not?
>>
>> If you're implementing level 1 (two-party), then really the only place
>> where this applies is when you receive a capability that the receiver hosts
>> as part of a return or resolve after you have made calls on the promised
>> capability.  This implies that the RPC system needs to keep track of which
>> parts of the answer have had calls made on them.  When this occurs, the
>> receiver gives the application code an embargoed client, and then sends a
>> Disembargo with senderLoopback set.  It releases the embargo once the same
>> disembargo ID is returned with receiverLoopback set.

Maybe I got this bit wrong. I attached the "used" flags to the
question, but maybe I should be tagging the reference to the question
instead. Can different references to the same question need different
disembargoes? e.g. should forwarding a message mark the promised
answer as needing a disembargo or not?

> Example:

That example is straight-forward, but there are more complex cases
that are unclear to me. Here's one I'm not sure about:

There are two vats, Client and Server, each of which starts with a
reference to the other's bootstrap service. All calls either return a
single capability (field-name `x`) or Void.

1. Client makes a call, q1, on the server's bootstrap object, getting
a promise a=q1.x
2. Client makes another call, q2, on the same target, getting promise b=q2.x.
3. Server asks one question, q3 (c=q3.x)
4. Client responds to q3 with a (the unresolved promised cap from its q1)
5. Server responds to q1 with client_bs (the client's bootstrap
service, resolved)
6. Server responds to q2 with c (q3.x, still unresolved)
7. Client makes call m1 on b (sent to q2)
8. Client receives response a=client_bs (no embargo needed)
9. Client receives response b=q3.x, which is a.
    This was q1.x at the time q3 returned, but client_bs now. Which
should it use?
    If client_bs, it embargoes the target due to m1.
    If not, b now points at the returned q1, which seems odd.
10. Client makes call m2 on b (which is then held at the embargo).
11. Server receives response that c=q1.x (which is client_bs).
12. Server receives m1 and forwards it to q3.x.
13. Server sends disembargo response back to client.
14. Client receives m1 and forwards it to q1 (the resolution it gave for q3).
15. Client disembargoes b and sends m2 to client_bs.

(sorry if this is unclear - I've put up a diagram of it here:
https://github.com/mirage/capnp-rpc/issues/59)

With b set to the embargoed client_bs in step 9, m2 arrives before m1
(which is now on its way back to the server again). Perhaps a second
disembargo is needed?

Alternatively, if b was set to point at q1.x, I think the messages
will arrive in the correct order.
But then b ends up pointing to the answered q1, rather than directly
at client_bs.

As a third alternative, if messages are sent to their current, more
resolved destination (ignoring the spec) then this case works, but can
be made to break by sending another message down q3 before m1 arrives
at c. Then the server embargoes m1, and m2 arrives first again.

Could someone point me in the right direction?

Thanks,


-- 
talex5 (GitHub/Twitter)        http://roscidus.com/blog/
GPG: 5DD5 8D70 899C 454A 966D  6A51 7513 3C8F 94F6 E0CC

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.

Reply via email to