update %clay doc

This commit is contained in:
Ubuntu 2014-09-05 16:25:02 +00:00
parent f84354bdcd
commit afb776f077

View File

@ -602,6 +602,28 @@ version reported (since a range of versions may be requested in a
subscription). `r.p` is the desk. `q` is the path to the filesystem node.
`r` is the data itself (in the format specified by `p.p`).
###`++nako`, subscription response data
```
++ nako $: gar=(map ,@ud tako) :: new ids
let=@ud :: next id
lar=(set yaki) :: new commits
bar=(set blob) :: new content
== ::
```
This is the data that is produced by a request for a range of revisions of a
desk.
`gar` is a map of the revisions in the range to the hash of the commit
at that revision. These hashes can be used with `hut:rang` to find the commit
itself.
`let` is either the last revision number in the range or the most recent
revision number, whichever is smaller.
`lar` is the set of new commits, and `bar` is the set of new content.
Interface
---------
@ -720,8 +742,8 @@ another ship and, being a global filesystem, clay will happily produce it for
you. That code pathway will be described in another section; here, we will
restrict ourselves to examining the case of a read from a ship on our own pier.
The kiss can request either a single version of a file or a range of versions
of a desk. We'll trace through both paths at once.
The kiss can request either a single version of a file node or a range of
versions of a desk. Here, we'll deal only with a request for a single version.
As in all vanes, a kiss enters clay via a call to `++call`. Scanning through
the arm, we quickly see where `%warp` is handled.
@ -1295,6 +1317,77 @@ If we're requesting the revision number of the desk and we're not requesting it
by number, then we just return the current number of this desk. Note of course
that this was really already handled in `++avid`.
If we're requesting a `%w` with a specific revision number, then we do
something or other with the commit there. It's kind of weird, and it doesn't
seem to work, so we'll ignore this case.
Otherwise, we descend into the ankh tree with `++deny:zu` to the given path,
and then we handle specific request in `++amor`.
```
++ deny :: descend recursively
|= way=path
^+ +>
?~(way +> $(way t.way, +> (dent i.way)))
```
This is simple recursion down into the ankh tree. `++dent` descends one level,
so this will eventually get us down to the path we want.
```
++ dent :: descend
|= lol=@ta
^+ +>
=+ you=(~(get by r.ank) lol)
+>.$(ram [lol ram], ank ?~(you [*cash ~ ~] u.you))
```
`ram` is the path that we're at, so to descend one level we push the name of
this level onto that path. We update the ankh with the correct one at that
path if it exists; else we create a blank one.
Once we've decscended to the correct level, we need to actually deal with the
request.
```
++ amor :: amor:ze
|= ren=?(%u %v %x %y %z) :: endpoint query
^- (unit ,*)
?- ren
%u [~ `rang`+<+>.amor]
%v [~ `dome`+<+<.amor]
%x ?~(q.ank ~ [~ q.u.q.ank])
%y [~ ache]
%z [~ ank]
==
```
Now that everything's set up, it's really easy. If they're requesting the rang
, dome, or ankh, we give it to them. If the contents of a file, we give it to
them if it is in fact a file. If the `arch`, then we calculate it with `++ache`.
```
++ ache :: ache:ze
^- arch :: arch report
:+ p.ank
?~(q.ank ~ [~ p.u.q.ank])
|- ^- (map ,@ta ,~)
?~ r.ank ~
[[p.n.r.ank ~] $(r.ank l.r.ank) $(r.ank r.r.ank)]
```
This very simply strips out all the "real" data and returns just our own hash,
the hash of the file contents (if we're a file), and a map of the names of our
immediate children.
Lifecycle of a Local Subscription
---------------------------------
A subscription to a range of revisions of a desk initially follows the same
path that a single read does. In `++aver`, we checked the head of the given
rave. If the head was `&`, then it was a single request, so we handled it
above. If `|`, then we handle it with the following code.
```
|
=+ nab=(~(aeon ze lim dom ran) p.p.rav)
@ -1315,4 +1408,143 @@ that this was really already handled in `++avid`.
==
```
(this is from `++eave`)
Recall that `++aeon:ze` produces the revision number that a case corresponds
to, if it corresponds to any. If it doesn't yet correspond to a revision, then
it produces null.
Thus, we first check to see if we've even gotten to the beginning of the range
of revisions requested. If not, then we assert that we haven't yet gotten to
the end of the range either, because that would be really strange. If not,
then we immediately call `++duce`, which, if you recall, for a local request,
simply puts this duct and rave into our cult `qyx`, so that we know who to
respond to when the revision does appear.
If we've already gotten to the first revision, then we can produce some content
immediately. If we've also gotten to the final revision, and that revision is
earlier than the start revision, then it's a bad request and we call `++blub`,
which tells the subscriber that his subscription will not be satisfied.
Otherwise, we call `++gack`, which creates the `++nako` we need to produce. We
call `++bleb` to actually produce the information. If we already have the last
requested revision, then we also tell the subscriber with `++blub` that the
subscription will receive no further updates.
If there will be more revisions, that we'll need to report, then we call
`++duce`, adding the duct to our subscribers. We modify the rave to start at
the next revision since we've already handled all the revisions up to the
present.
We glossed over the calls to `++gack` and `++bleb`, so we'll get back to those
right now. `++bleb` is simple, so we'll start with that.
```
++ bleb :: ship sequence
|= [hen=duct ins=@ud hip=nako]
^+ +>
(blab hen [%w [%ud ins] ~] hip)
```
We're given a duct, the beginning revision number, and the nako that contains
the updates since that revision. We use `++blab` to produce this result to
the subscriber. The case is `%w` with a revision number of the beginning of the
subscription, and the data is the nako itself.
Finally, we will describe `++gack:ze`.
```
++ gack :: gack a through b
|= [a=@ud b=@ud]
^- [(map ,@ud tako) @ud (set yaki) (set blob)]
:_ :- b
%- hack
%+ pack
(~(get by hit) a) :: if a not found, a=0
%- need (~(get by hit) b)
^- (map ,@ud tako)
%- mo %+ skim (~(tap by hit) ~)
|= [p=@ud *]
&((gth p a) (lte p b))
```
```
++ hack :: trivial
|= [a=(set tako) b=(set lobe)]
^- [(set yaki) (set blob)]
:- %- sa %+ turn (~(tap by a) ~)
|= tak=tako
(need (~(get by hut) tak))
%- sa %+ turn (~(tap by b) ~)
|= lob=lobe
(need (~(get by lat) lob))
```
The type signature says everything you need to know about this. We take a set
of hashes of commits and data and convert them into the actual commits and data
in the most straightforward way possible.
```
++ pack
|= [a=(unit tako) b=tako] :: pack a through b
^- [(set tako) (set lobe)]
=+ ^= sar
?~ a ~
(zule r:(need (~(get by hut) u.a)))
=+ yak=`yaki`(need (~(get by hut) b))
%+ garf (garg ~ sar) :: get lobes
|- ^- (set tako) :: walk onto sar
?: (~(has in sar) r.yak)
~
=+ ber=`(set tako)`(~(put in `(set tako)`~) `tako`r.yak)
%- ~(uni in ber)
^- (set tako)
%+ roll p.yak
|= [yek=tako bar=(set tako)]
^- (set tako)
?: (~(has in bar) yek) :: save some time
bar
%- ~(uni in bar)
^$(yak (need (~(get by hut) yek)))
```
```
++ zule :: reachable
|= p=tako :: XX slow
^- (set tako)
=+ y=(~(got by hut) p)
=+ t=(~(put in _(set tako)) p)
%+ roll p.y
|= [q=tako s=_t]
?: (~(has in s) q) :: already done
s :: hence skip
(~(uni in s) ^$(p q)) :: otherwise traverse
```
```
++ garg :: object hash set
|= [b=(set lobe) a=(set tako)] :: that aren't in b
^- (set lobe)
%+ roll (~(tap in a) ~)
|= [tak=tako bar=(set lobe)]
^- (set lobe)
=+ yak=(need (~(get by hut) tak))
%+ roll (~(tap by q.yak) ~)
|= [[path lob=lobe] far=_bar]
^- (set lobe)
?~ (~(has in b) lob) :: don't need
far
=+ gar=(need (~(get by lat) lob))
?- -.gar
%direct (~(put in far) lob)
%delta (~(put in $(lob q.gar)) lob)
%indirect (~(put in $(lob s.gar)) lob)
==
```
```
++ garf :: garg & repack
|= [b=(set lobe) a=(set tako)]
^- [(set tako) (set lobe)]
[a (garg b a)]
```