@@ -0,0 +1,2626 @@
1++++
2+title = "Clay"
3+weight = 3
4+template = "doc.html"
5+aliases = ["/docs/learn/arvo/clay/"]
6++++
7+Our filesystem.
8+
9+`%clay` is version-controlled, referentially-transparent, and global.
10+While this filesystem is stored in `%clay`, it is mirrored to Unix for
11+convenience. Unix tells `%clay`s whenever a file changes in the Unix
12+copy of the filesystem so that the change may be applied. `%clay` tells
13+unix whenever an app or vane changes the filesystem so that the change
14+can be effected in Unix. Apps and vanes may use `%clay` to write to the
15+filesystem, query it, and subscribe to changes in it. Ford and gall use
16+`%clay` to serve up apps and web pages.
17+
18+`%clay` includes three components. First is the filesystem/version
19+control algorithms, which are mostly defined in `++ze` and `++zu` in
20+zuse. Second is the write, query, and subscription logic. Finally, there
21+is the logic for communicating requests to, and receiving requests from,
22+foreign ships.
23+
24+## Architecture
25+
26+Clay is the primary filesystem for the arvo operating system,
27+which is the core of an urbit. The architecture of clay is
28+intrinsically connected with arvo, but we assume no knowledge of
29+either arvo or urbit. We will point out only those features of
30+arvo that are necessary for an understanding of clay, and we will
31+do so only when they arise.
32+
33+The first relevant feature of arvo is that it is a deterministic
34+system where input and output are defined as a series of events
35+and effects. The state of arvo is simply a function of its event
36+log. None of the effects from an event are emitted until the
37+event is entered in the log and persisted, either to disk or
38+another trusted source of persistence, such as a Kafka cluster.
39+Consequently, arvo is a single-level store: everything in its
40+state is persistent.
41+
42+In a more traditional OS, everything in RAM can be erased at any
43+time by power failure, and is always erased on reboot. Thus, a
44+primary purpose of a filesystem is to ensure files persist across
45+power failures and reboots. In arvo, both power failures and
46+reboots are special cases of suspending computation, which is
47+done safely since our event log is already persistent. Therefore,
48+clay is not needed in arvo for persistence. Why, then, do we have a
49+filesystem? There are two answers to this question.
50+
51+First, clay provides a filesystem tree, which is a convenient
52+user interface for some applications. Unix has the useful concept
53+of virtual filesystems, which are used for everything from direct
54+access to devices, to random number generators, to the /proc
55+tree. It is easy and intuitive to read from and write to a
56+filesystem tree.
57+
58+Second, clay has a distributed revision-control system baked into
59+it. Traditional filesystems are not revision controlled, so
60+userspace software -- such as git -- is written on top of them to
61+do so. clay natively provides the same functionality as modern
62+DVCSes, and more.
63+
64+clay has two other unique properties that we'll cover later on:
65+it supports typed data and is referentially transparent.
66+
67+### Revision Control
68+
69+Every urbit has one or more "desks", which are independently
70+revision-controlled branches. Each desk contains its own mark
71+definitions, apps, doc, and so forth.
72+
73+Traditionally, an urbit has at least a base and a home desk. The
74+base desk has all the system software from the distribution. the
75+home desk is a fork of base with all the stuff specific to the
76+user of the urbit.
77+
78+A desk is a series of numbered commits, the most recent of which
79+represents the current state of the desk. A commit is composed of
80+(1) an absolute time when it was created, (2) a list of zero or
81+more parents, and (3) a map from paths to data.
82+
83+Most commits have exactly one parent, but the initial commit on a
84+desk may have zero parents, and merge commits have more than one
85+parent.
86+
87+The non-meta data is stored in the map of paths to data. It's
88+worth noting that no constraints are put on this map, so, for
89+example, both /a/b and /a/b/c could have data. This is impossible
90+in a traditional Unix filesystem since it means that /a/b is both
91+a file and a directory. Conventionally, the final element in the
92+path is its mark -- much like a filename extension in Unix. Thus,
93+/doc/readme.md in Unix is stored as /doc/readme/md in urbit.
94+
95+The data is not stored directly in the map; rather, a hash of the
96+data is stored, and we maintain a master blob store. Thus, if the
97+same data is referred to in multiple commits (as, for example,
98+when a file doesn't change between commits), only the hash is
99+duplicated.
100+
101+In the master blob store, we either store the data directly, or
102+else we store a diff against another blob. The hash is dependent
103+only on the data within and not on whether or not it's stored
104+directly, so we may on occasion rearrange the contents of the
105+blob store for performance reasons.
106+
107+Recall that a desk is a series of numbered commits. Not every
108+commit in a desk must be numbered. For example, if the base desk
109+has had 50 commits since home was forked from it, then a merge
110+from base to home will only add a single revision number to home,
111+although the full commit history will be accessible by traversing
112+the parentage of the individual commits.
113+
114+We do guarantee that the first commit is numbered 1, commits are
115+numbered consecutively after that (i.e. there are no "holes"),
116+the topmost commit is always numbered, and every numbered commit
117+is an ancestor of every later numbered commit.
118+
119+There are three ways to refer to particular commits in the
120+revision history. Firstly, one can use the revision number.
121+Secondly, one can use any absolute time between the one numbered
122+commit and the next (inclusive of the first, exclusive of the
123+second). Thirdly, every desk has a map of labels to revision
124+numbers. These labels may be used to refer to specific commits.
125+
126+Additionally, clay is a global filesystem, so data on other urbit
127+is easily accessible the same way as data on our local urbit. In
128+general, the path to a particular revision of a desk is
129+/~urbit-name/desk-name/revision. Thus, to get /try/readme/md
130+from revision 5 of the home desk on ~sampel-sipnym, we refer to
131+/~sampel-sipnym/home/5/try/readme/md. Clay's namespace is thus
132+global and referentially transparent.
133+
134+XXX reactivity here?
135+
136+### A Typed Filesystem
137+
138+Since clay is a general filesystem for storing data of arbitrary
139+types, in order to revision control correctly it needs to be
140+aware of types all the way through. Traditional revision control
141+does an excellent job of handling source code, so for source code
142+we act very similar to traditional revision control. The
143+challenge is to handle other data similarly well.
144+
145+For example, modern VCSs generally support "binary files", which
146+are files for which the standard textual diffing, patching, and
147+merging algorithms are not helpful. A "diff" of two binary files
148+is just a pair of the files, "patching" this diff is just
149+replacing the old file with the new one, and "merging"
150+non-identical diffs is always a conflict, which can't even be
151+helpfully annotated. Without knowing anything about the structure
152+of a blob of data, this is the best we can do.
153+
154+Often, though, "binary" files have some internal structure, and
155+it is possible to create diff, patch, and merge algorithms that
156+take advantage of this structure. An image may be the result of a
157+base image with some set of operations applied. With algorithms
158+aware of this set of operations, not only can revision control
159+software save space by not having to save every revision of the
160+image individually, these transformations can be made on parallel
161+branches and merged at will.
162+
163+Suppose Alice is tasked with touching up a picture, improving the
164+color balance, adjusting the contrast, and so forth, while Bob
165+has the job of cropping the picture to fit where it's needed and
166+adding textual overlay. Without type-aware revision control,
167+these changes must be made serially, requiring Alice and Bob to
168+explicitly coordinate their efforts. With type-aware revision
169+control, these operations may be performed in parallel, and then
170+the two changesets can be merged programmatically.
171+
172+Of course, even some kinds of text files may be better served by
173+diff, patch, and merge algorithms aware of the structure of the
174+files. Consider a file containing a pretty-printed JSON object.
175+Small changes in the JSON object may result in rather significant
176+changes in how the object is pretty-printed (for example, by
177+addding an indentation level, splitting a single line into
178+multiple lines).
179+
180+A text file wrapped at 80 columns also reacts suboptimally with
181+unadorned Hunt-McIlroy diffs. A single word inserted in a
182+paragraph may push the final word or two of the line onto the
183+next line, and the entire rest of the paragraph may be flagged as
184+a change. Two diffs consisting of a single added word to
185+different sentences may be flagged as a conflict. In general,
186+prose should be diffed by sentence, not by line.
187+
188+As far as the author is aware, clay is the first generalized,
189+type-aware revision control system. We'll go into the workings
190+of this system in some detail.
191+
192+### Marks
193+
194+Central to a typed filesystem is the idea of types. In clay, we
195+call these "marks". A mark is a file that defines a type,
196+conversion routines to and from the mark, and diff, patch, and
197+merge routines.
198+
199+For example, a `%txt` mark may be a list of lines of text, and it
200+may include conversions to `%mime` to allow it to be serialized
201+and sent to a browswer or to the unix filesystem. It will also
202+include Hunt-McIlroy diff, patch, and merge algorithms.
203+
204+A `%json` mark would be defined as a json object in the code, and
205+it would have a parser to convert from `%txt` and a printer to
206+convert back to `%txt`. The diff, patch, and merge algorithms are
207+fairly straightforward for json, though they're very different
208+from the text ones.
209+
210+More formally, a mark is a core with three arms, `++grab`,
211+`++grow`, and `++grad`. In `++grab` is a series of functions to
212+convert from other marks to the given mark. In `++grow` is a
213+series of functions to convert from the given mark to other
214+marks. In `++grad` is `++diff`, `++pact`, `++join`, and `++mash`.
215+
216+The types are as follows, in an informal pseudocode:
217+
218+```
219+ ++ grab:
220+ ++ mime: <mime> -> <mark-type>
221+ ++ txt: <txt> -> <mark-type>
222+ ...
223+ ++ grow:
224+ ++ mime: <mark-type> -> <mime>
225+ ++ txt: <mark-type> -> <txt>
226+ ...
227+ ++ grad
228+ ++ diff: (<mark-type>, <mark-type>) -> <diff-type>
229+ ++ pact: (<mark-type>, <diff-type>) -> <mark-type>
230+ ++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
231+ ++ mash: (<diff-type>, <diff-type>) -> <diff-type>
232+```
233+
234+These types are basically what you would expect. Not every mark
235+has each of these functions defined -- all of them are optional
236+in the general case.
237+
238+In general, for a particular mark, the `++grab` and `++grow` entries
239+(if they exist) should be inverses of each other.
240+
241+In `++grad`, `++diff` takes two instances of a mark and produces
242+a diff of them. `++pact` takes an instance of a mark and patches
243+it with the given diff. `++join` takes two diffs and attempts to
244+merge them into a single diff. If there are conflicts, it
245+produces null. `++mash` takes two diffs and forces a merge,
246+annotating any conflicts.
247+
248+In general, if `++diff` called with A and B produces diff D, then
249+`++pact` called with A and D should produce B. Also, if `++join`
250+of two diffs does not produce null, then `++mash` of the same
251+diffs should produce the same result.
252+
253+Alternately, instead of `++diff`, `++pact`, `++join`, and
254+`++mash`, a mark can provide the same functionality by defining
255+`++sted` to be the name of another mark to which we wish to
256+delegate the revision control responsibilities. Then, before
257+running any of those functions, clay will convert to the other
258+mark, and convert back afterward. For example, the `%hoon` mark
259+is revision-controlled in the same way as `%txt`, so its `++grad`
260+is simply `++sted %txt`. Of course, `++txt` must be defined in
261+`++grow` and `++grab` as well.
262+
263+Every file in clay has a mark, and that mark must have a
264+fully-functioning `++grad`. Marks are used for more than just
265+clay, and other marks don't need a `++grad`, but if a piece of
266+data is to be saved to clay, we must know how to revision-control
267+it.
268+
269+Additionally, if a file is to be synced out to unix, then it must
270+have conversion routines to and from the `%mime` mark.
271+
272+## Using clay
273+
274+### Reading and Subscribing
275+
276+When reading from Clay, there are three types of requests. A
277+`%sing` request asks for data at single revsion. A `%next`
278+request asks to be notified the next time there's a change to
279+given file. A `%many` request asks to be notified on every
280+change in a desk for a range of changes.
281+
282+For `%sing` and `%next`, there are generally three things to be
283+queried. A `%u` request simply checks for the existence of a
284+file at a path. A `%x` request gets the data in the file at a
285+path. A `%y` request gets a hash of the data in the file at the
286+path combined with all its children and their data. Thus, `%y`
287+of a node changes if it or any of its children change.
288+
289+A `%sing` request is fulfilled immediately if possible. If the
290+requested revision is in the future, or is on another ship for
291+which we don't have the result cached, we don't respond
292+immediately. If the requested revision is in the future, we wait
293+until the revision happens before we respond to the request. If
294+the request is for data on another ship, we pass on the request
295+to the other ship. In general, Clay subscriptions, like most
296+things in Urbit, aren't guaranteed to return immediately.
297+They'll return when they can, and they'll do so in a
298+referentially transparent manner.
299+
300+A `%next` request checks query at the given revision, and it
301+produces the result of the query the next time it changes, along
302+with the revsion number when it changes. Thus, a `%next` of a
303+`%u` is triggered when a file is added or deleted, a `%next` of a
304+`%x` is triggered when a file is added, deleted, or changed, and
305+a `%next` of a `%y` is triggered when a file or any of its
306+children is added, deleted, or changed.
307+
308+A `%many` request is triggered every time the given desk has a
309+new revision. Unlike a `%next`, a `%many` has both a start and
310+an end revsion, after which it stops returning. For `%next`, a
311+single change is reported, and if the caller wishes to hear of
312+the next change, it must resubscribe. For `%many`, every revsion
313+from the start to the end triggers a response. Since a `%many`
314+request doesn't ask for any particular data, there aren't `%u`,
315+`%x`, and `%y` versions for it.
316+
317+### Unix sync
318+
319+One of the primary functions of clay is as a convenient user
320+interface. While tools exist to use clay from within urbit, it's
321+often useful to be able to treat clay like any other filesystem
322+from the Unix perspective -- to "mount" it, as it were.
323+
324+From urbit, you can run `|mount /path/to/directory %mount-point`,
325+and this will mount the given clay directory to the mount-point
326+directory in Unix. Every file is converted to `%mime` before it's
327+written to Unix, and converted back when read from Unix. The
328+entire directory is watched (a la Dropbox), and every change is
329+committed once you run `|commit %mount-point`.
330+
331+### Merging
332+
333+Merging is a fundamental operation for a distributed revision
334+control system. At their root, clay's merges are similar to
335+git's, but with some additions to accomodate typed data. There
336+are seven different merge strategies.
337+
338+Throughout our discussion, we'll say that the merge is from
339+Alice's desk to Bob's. Recall that a commit is a date (for all
340+new commits this will be the current date), a list of parents,
341+and the data itself.
342+
343+A `%init` merge should be used iff it's the first commit to a
344+desk. The head of Alice's desk is used as the number 1 commit to
345+Bob's desk. Obviously, the ancestry remains intact through
346+traversing the parentage of the commit even though previous
347+commits are not numbered for Bob's desk.
348+
349+A `%this` merge means to keep what's in Bob's desk, but join the
350+ancestry. Thus, the new commit has the head of each desk as
351+parents, but the data is exactly what's in Bob's desk. For those
352+following along in git, this is the 'ours' merge strategy, not
353+the '--ours' option to the 'recursive' merge strategy. In other
354+words, even if Alice makes a change that does not conflict with
355+Bob, we throw it away. It's Bob's way or the highway.
356+
357+A `%that` merge means to take what's in Alice's desk, but join
358+the ancestry. This is the reverse of `%this`.
359+
360+A `%fine` merge is a "fast-forward" merge. This succeeds iff one
361+head is in the ancestry of the other. In this case, we use the
362+descendant as our new head.
363+
364+For `%meet`, `%mate`, and `%meld` merges, we first find the most
365+recent common ancestor to use as our merge base. If we have no
366+common ancestors, then we fail. If we have more than one most
367+recent common ancestor, then we have a criss-cross situation,
368+which should be handled delicately. At present, we delicately
369+throw up our hands and give up, but something akin to git's
370+'recursive' strategy should be implemented in the future.
371+
372+There's a functional inclusion ordering on `%fine`, `%meet`,
373+`%mate`, and `%meld` such that if an earlier strategy would have
374+succeeded, then every later strategy will produce the same
375+result. Put another way, every earlier strategy is the same as
376+every later strategy except with a restricted domain.
377+
378+A `%meet` merge only succeeds if the changes from the merge base
379+to Alice's head (hereafter, "Alice's changes") are in different
380+files than Bob's changes. In this case, the parents are both
381+Alice's and Bob's heads, and the data is the merge base plus
382+Alice's changed files plus Bob's changed files.
383+
384+A `%mate` merge attempts to merge changes to the same file when
385+both Alice and bob change it. If the merge is clean, we use it;
386+otherwise, we fail. A merge between different types of changes --
387+for example, deleting a file vs changing it -- is always a
388+conflict. If we succeed, the parents are both Alice's and Bob's
389+heads, and the data is the merge base plus Alice's changed files
390+plus Bob's changed files plus the merged files.
391+
392+A `%meld` merge will succeed even if there are conflicts. If
393+there are conflicts in a file, then we use the merge base's
394+version of that file, and we produce a set of files with
395+conflicts. The parents are both Alice's and Bob's heads, and the
396+data is the merge base plus Alice's changed files plus Bob's
397+changed files plus the successfully merged files plus the merge
398+base's version of the conflicting files.
399+
400+That's the extent of the merge options in clay proper. In
401+userspace there's a final option `%auto`, which is the most
402+common. `%auto` checks to see if Bob's desk exists, and if it
403+doesn't we use a `%init` merge. Otherwise, we progressively try
404+`%fine`, `%meet`, and `%mate` until one succeeds.
405+
406+If none succeed, we merge Bob's desk into a scratch desk. Then,
407+we merge Alice's desk into the scratch desk with the `%meld`
408+option to force the merge. For each file in the produced set of
409+conflicting files, we call the `++mash` function for the
410+appropriate mark, which annotates the conflicts if we know how.
411+
412+Finally, we display a message to the user informing them of the
413+scratch desk's existence, which files have annotated conflicts,
414+and which files have unannotated conflicts. When the user has
415+resolved the conflicts, they can merge the scratch desk back into
416+Bob's desk. This will be a `%fine` merge since Bob's head is in
417+the ancestry of the scratch desk.
418+
419+### Autosync
420+
421+Tracking and staying in sync with another desk is another
422+fundamental operation. We call this "autosync". This doesn't mean
423+simply mirroring a desk, since that wouldn't allow local changes.
424+We simply want to apply changes as they are made upstream, as
425+long as there are no conflicts with local changes.
426+
427+This is implemented by watching the other desk, and, when it has
428+changes, merging these changes into our desk with the usual merge
429+strategies.
430+
431+Note that it's quite reasonable for two desks to be autosynced to
432+each other. This results in any change on one desk being mirrored
433+to the other and vice versa.
434+
435+Additionally, it's fine to set up an autosync even if one desk,
436+the other desk, or both desks do not exist. The sync will be
437+activated when the upstream desk comes into existence and will
438+create the downstream desk if needed.
439+
440+## Commentary
441+
442+The first part of this section will be reference documentation for the data
443+types used by our filesystem. In fact, as a general guide, we recommend
444+reading and attempting to understand the data structures used in any
445+Hoon code before you try to read the code itself. Although complete
446+understanding of the data structures is impossible without seeing them
447+used in the code, an 80% understanding greatly clarifies the code. As
448+another general guide, when reading Hoon, it rarely pays off to
449+understand every line of code when it appears. Try to get the gist of
450+it, and then move on. The next time you come back to it, it'll likely
451+make a lot more sense.
452+
453+After a description of the data models, we'll give an overview of the
454+interface that vanes and applications can use to interact with the
455+filesystem.
456+
457+Finally, we'll dive into the code and the algorithms themselves. You
458+know, the fun part.
459+
460+### Data Models
461+
462+As you're reading through this section, remember you can always come
463+back to this when you run into these types later on. You're not going to
464+remember everything the first time through, but it is worth reading, or
465+at least skimming, this so that you get a rough idea of how our state is
466+organized.
467+
468+The types that are certainly worth reading are `++raft`, `++room`,
469+`++dome:clay`, `++ankh:clay`, `++rung:clay`, `++rang:clay`, `++blob:clay`, `++yaki:clay`, and `++nori:clay`
470+(possibly in that order). All in all, though, this section isn't too
471+long, so many readers may wish to quickly read through all of it. If you
472+get bored, though, just skip to the next section. You can always come
473+back when you need to.
474+
475+### `++raft`, formal state
476+
477+```hoon
478+ ++ raft :: filesystem
479+ $: fat=(map ship room) :: domestic
480+ hoy=(map ship rung) :: foreign
481+ ran=rang :: hashes
482+ == ::
483+```
484+
485+This is the state of our vane. Anything that must be remembered between
486+calls to clay is stored in this state.
487+
488+`fat` is the set of domestic servers. This stores all the information
489+that is specfic to a particular ship on this pier. The keys to this map
490+are the ships on the current pier. all the information that is specific
491+to a particular foreign ship. The keys to this map are all the ships
492+whose filesystems we have attempted to access through clay.
493+
494+`ran` is the store of all commits and deltas, keyed by hash. The is
495+where all the "real" data we know is stored; the rest is "just
496+bookkeeping".
497+
498+#### `++room`, filesystem per domestic ship
499+
500+```hoon
501+ ++ room :: fs per ship
502+ $: hun=duct :: terminal duct
503+ hez=(unit duct) :: sync duch
504+ dos=(map desk dojo) :: native desk
505+ == ::
506+```
507+
508+This is the representation of the filesystem of a ship on our pier.
509+
510+`hun` is the duct we use to send messages to dill to display
511+notifications of filesystem changes. Only `%note` gifts should be
512+produced along this duct. This is set by the `%init` kiss.
513+
514+`hez`, if present, is the duct we use to send sync messages to unix so
515+that they end up in the pier unix directory. Only `%ergo` gifts should
516+be producd along this duct. This is set by `%into` and `%invo` kisses.
517+
518+`dos` is a well-known operating system released in 1981. It is also the
519+set of desks on this ship, mapped to their data.
520+
521+#### `++desk`, filesystem branch
522+
523+```hoon
524+ ++ desk ,@tas :: ship desk case spur
525+```
526+
527+This is the name of a branch of the filesystem. The default desks are
528+"arvo", "main", and "try". More may be created by simply referencing
529+them. Desks have independent histories and states, and they may be
530+merged into each other.
531+
532+### `++dojo`, domestic desk state
533+
534+```hoon
535+ ++ dojo ,[p=cult q=dome] :: domestic desk state
536+```
537+
538+This is the all the data that is specific to a particular desk on a
539+domestic ship. `p` is the set of subscribers to this desk and `q` is the
540+data in the desk.
541+
542+#### `++cult`, subscriptions
543+
544+```hoon
545+ ++ cult (map duct rave) :: subscriptions
546+```
547+
548+This is the set of subscriptions to a particular desk. The keys are the
549+ducts from where the subscriptions requests came. The results will be
550+produced along these ducts. The values are a description of the
551+requested information.
552+
553+#### `++rave:clay`, general subscription request
554+
555+```hoon
556+ ++ rave :: general request
557+ $% [& p=mood] :: single request
558+ [| p=moat] :: change range
559+ == ::
560+```
561+
562+This represents a subscription request for a desk. The request can be
563+for either a single item in the desk or else for a range of changes on
564+the desk.
565+
566+### `++rove`, stored general subscription request
567+
568+```hoon
569+ ++ rove (each mood moot) :: stored request
570+```
571+
572+When we store a request, we store subscriptions with a little extra
573+information so that we can determine whether new versions actually
574+affect the path we're subscribed to.
575+
576+#### `++mood:clay`, single subscription request
577+
578+```hoon
579+ ++ mood ,[p=care q=case r=path] :: request in desk
580+```
581+
582+This represents a request for the state of the desk at a particular
583+commit, specfied by `q`. `p` specifies what kind of information is
584+desired, and `r` specifies the path we are requesting.
585+
586+#### `++moat:clay`, range subscription request
587+
588+```hoon
589+ ++ moat ,[p=case q=case r=path] :: change range
590+```
591+
592+This represents a request for all changes between `p` and `q` on path
593+`r`. You will be notified when a change is made to the node referenced
594+by the path or to any of its children.
595+
596+### `++moot`, stored range subscription request
597+
598+```hoon
599+ ++ moot ,[p=case q=case r=path s=(map path lobe)] ::
600+```
601+
602+This is just a `++moat:clay` plus a map of paths to lobes. This map
603+represents the data at the node referenced by the path at case `p`, if
604+we've gotten to that case (else null). We only send a notification along
605+the subscription if the data at a new revision is different than it was.
606+
607+### `++care:clay`, clay submode
608+
609+```hoon
610+ ++ care ?(%u %v %w %x %y %z) :: clay submode
611+```
612+
613+This specifies what type of information is requested in a subscription
614+or a scry.
615+
616+`%u` requests the `++rang:clay` at the current moment. Because this
617+information is not stored for any moment other than the present, we
618+crash if the `++case:clay` is not a `%da` for now.
619+
620+`%v` requests the `++dome:clay` at the specified commit.
621+
622+`%w` requests the revsion number of the desk.
623+
624+`%x` requests the file at a specified path at the specified commit. If
625+there is no node at that path or if the node has no contents (that is,
626+if `q:ankh` is null), then this produces null.
627+
628+`%y` requests a `++arch` of the specfied commit at the specified path.
629+
630+`%z` requests the `++ankh` of the specified commit at the specfied path.
631+
632+### `++arch`, shallow filesystem node
633+
634+```hoon
635+ ++ arch ,[p=@uvI q=(unit ,@uvI) r=(map ,@ta ,~)] :: fundamental node
636+```
637+
638+This is analogous to `++ankh:clay` except that the we have neither our
639+contents nor the ankhs of our children. The other fields are exactly the
640+same, so `p` is a hash of the associated ankh, `u.q`, if it exists, is a
641+hash of the contents of this node, and the keys of `r` are the names of
642+our children. `r` is a map to null rather than a set so that the
643+ordering of the map will be equivalent to that of `r:ankh`, allowing
644+efficient conversion.
645+
646+#### `++case:clay`, specifying a commit
647+
648+```hoon
649+ ++ case :: ship desk case spur
650+ $% [%da p=@da] :: date
651+ [%tas p=@tas] :: label
652+ [%ud p=@ud] :: number
653+ == ::
654+```
655+
656+A commit can be referred to in three ways: `%da` refers to the commit
657+that was at the head on date `p`, `%tas` refers to the commit labeled
658+`p`, and `%ud` refers to the commit numbered `p`. Note that since these
659+all can be reduced down to a `%ud`, only numbered commits may be
660+referenced with a `++case:clay`.
661+
662+#### `++dome:clay`, desk data
663+
664+```hoon
665+ ++ dome :: project state
666+ $: ang=agon :: pedigree
667+ ank=ankh :: state
668+ let=@ud :: top id
669+ hit=(map ,@ud tako) :: changes by id
670+ lab=(map ,@tas ,@ud) :: labels
671+ == ::
672+```
673+
674+This is the data that is actually stored in a desk.
675+
676+`ang` is unused and should be removed.
677+
678+`ank` is the current state of the desk. Thus, it is the state of the
679+filesystem at revison `let`. The head of a desk is always a numbered
680+commit.
681+
682+`let` is the number of the most recently numbered commit. This is also
683+the total number of numbered commits.
684+
685+`hit` is a map of numerical ids to hashes of commits. These hashes are
686+mapped into their associated commits in `hut:rang:clay`. In general, the keys
687+of this map are exactly the numbers from 1 to `let`, with no gaps. Of
688+course, when there are no numbered commits, `let` is 0, so `hit` is
689+null. Additionally, each of the commits is an ancestor of every commit
690+numbered greater than this one. Thus, each is a descendant of every
691+commit numbered less than this one. Since it is true that the date in
692+each commit (`t:yaki`) is no earlier than that of each of its parents,
693+the numbered commits are totally ordered in the same way by both
694+pedigree and date. Of course, not every commit is numbered. If that
695+sounds too complicated to you, don't worry about it. It basically
696+behaves exactly as you would expect.
697+
698+`lab` is a map of textual labels to numbered commits. Note that labels
699+can only be applied to numbered commits. Labels must be unique across a
700+desk.
701+
702+#### `++ankh`, filesystem node
703+
704+```hoon
705+ ++ ankh :: fs node (new)
706+ $: p=cash :: recursive hash
707+ q=(unit ,[p=cash q=*]) :: file
708+ r=(map ,@ta ankh) :: folders
709+ == ::
710+```
711+
712+This is a single node in the filesystem. This may be file or a directory
713+or both. In earth filesystems, a node is a file xor a directory. On
714+mars, we're inclusive, so a node is a file ior a directory.
715+
716+`p` is a recursive hash that depends on the contents of the this file or
717+directory and on any children.
718+
719+`q` is the contents of this file, if any. `p.q` is a hash of the
720+contents while `q.q` is the data itself.
721+
722+`r` is the set of children of this node. In the case of a pure file,
723+this is empty. The keys are the names of the children and the values
724+are, recursively, the nodes themselves.
725+
726+#### `++cash`, ankh hash
727+
728+```hoon
729+ ++ cash ,@uvH :: ankh hash
730+```
731+
732+This is a 128-bit hash of an ankh. These are mostly stored within ankhs
733+themselves, and they are used to check for changes in possibly-deep
734+hierarchies.
735+
736+#### `++rung`, filesystem per neighbor ship
737+
738+```hoon
739+ ++ rung $: rus=(map desk rede) :: neighbor desks
740+ == ::
741+```
742+
743+This is the filesystem of a neighbor ship. The keys to this map are all
744+the desks we know about on their ship.
745+
746+#### `++rede`, desk state
747+
748+```hoon
749+ ++ rede :: universal project
750+ $: lim=@da :: complete to
751+ qyx=cult :: subscribers
752+ ref=(unit rind) :: outgoing requests
753+ dom=dome :: revision state
754+ == ::
755+```
756+
757+This is our knowledge of the state of a desk, either foreign or
758+domestic.
759+
760+`lim` is the date of the last full update. We only respond to requests
761+for stuff before this time.
762+
763+`qyx` is the list of subscribers to this desk. For domestic desks, this
764+is simply `p:dojo`, all subscribers to the desk, while in foreign desks
765+this is all the subscribers from our ship to the foreign desk.
766+
767+`ref` is the request manager for the desk. For domestic desks, this is
768+null since we handle requests ourselves.
769+
770+`dom` is the actual data in the desk.
771+
772+#### `++rind`, request manager
773+
774+```hoon
775+ ++ rind :: request manager
776+ $: nix=@ud :: request index
777+ bom=(map ,@ud ,[p=duct q=rave]) :: outstanding
778+ fod=(map duct ,@ud) :: current requests
779+ haw=(map mood (unit)) :: simple cache
780+ == ::
781+```
782+
783+This is the request manager for a foreign desk.
784+
785+`nix` is one more than the index of the most recent request. Thus, it is
786+the next available request number.
787+
788+`bom` is the set of outstanding requests. The keys of this map are some
789+subset of the numbers between 0 and one less than `nix`. The members of
790+the map are exactly those requests that have not yet been fully
791+satisfied.
792+
793+`fod` is the same set as `bom`, but from a different perspective. In
794+particular, the values of `fod` are the same as the values of `bom`, and
795+the `p` out of the values of `bom` are the same as the keys of `fod`.
796+Thus, we can map ducts to their associated request number and `++rave:clay`,
797+and we can map numbers to their associated duct and `++rave:clay`.
798+
799+`haw` is a map from simple requests to their values. This acts as a
800+cache for requests that have already been made. Thus, the second request
801+for a particular `++mood:clay` is nearly instantaneous.
802+
803+#### `++rang:clay`, data store
804+
805+```hoon
806+ ++ rang $: hut=(map tako yaki) ::
807+ lat=(map lobe blob) ::
808+ == ::
809+```
810+
811+This is a set of data keyed by hash. Thus, this is where the "real" data
812+is stored, but it is only meaningful if we know the hash of what we're
813+looking for.
814+
815+`hut` is a map from hashes to commits. We often get the hashes from
816+`hit:dome:clay`, which keys them by logical id. Not every commit has an id.
817+
818+`lat` is a map from hashes to the actual data. We often get the hashes
819+from a `++yaki`, a commit, which references this map to get the data.
820+There is no `++blob:clay` in any `++yaki:clay`. They are only accessible through
821+this map.
822+
823+#### `++tako:clay`, commit reference
824+
825+```hoon
826+ ++ tako ,@ :: yaki ref
827+```
828+
829+This is a hash of a `++yaki:clay`, a commit. These are most notably used as
830+the keys in `hut:rang:clay`, where they are associated with the actual
831+`++yaki:clay`, and as the values in `hit:dome:clay`, where sequential ids are
832+associated with these.
833+
834+#### `++yaki:clay`, commit
835+
836+```hoon
837+ ++ yaki ,[p=(list tako) q=(map path lobe) r=tako t=@da] :: commit
838+```
839+
840+This is a single commit.
841+
842+`p` is a list of the hashes of the parents of this commit. In most
843+cases, this will be a single commit, but in a merge there may be more
844+parents. In theory, there may be an arbitrary number of parents, but in
845+practice merges have exactly two parents. This may change in the future.
846+For commit 1, there is no parent.
847+
848+`q` is a map of the paths on a desk to the data at that location. If you
849+understand what a `++lobe:clay` and a `++blob:clay` is, then the type signature
850+here tells the whole story.
851+
852+`r` is the hash associated with this commit.
853+
854+`t` is the date at which this commit was made.
855+
856+#### `++lobe:clay`, data reference
857+
858+```hoon
859+ ++ lobe ,@ :: blob ref
860+```
861+
862+This is a hash of a `++blob:clay`. These are most notably used in `lat:rang:clay`,
863+where they are associated with the actual `++blob:clay`, and as the values in
864+`q:yaki:clay`, where paths are associated with their data in a commit.
865+
866+#### `++blob:clay`, data
867+
868+```hoon
869+ ++ blob $% [%delta p=lobe q=lobe r=udon] :: delta on q
870+ [%direct p=lobe q=* r=umph] ::
871+ [%indirect p=lobe q=* r=udon s=lobe] ::
872+ == ::
873+```
874+
875+This is a node of data. In every case, `p` is the hash of the blob.
876+
877+`%delta` is the case where we define the data by a delta on other data.
878+In practice, the other data is always the previous commit, but nothing
879+depends on this. `q` is the hash of the parent blob, and `r` is the
880+delta.
881+
882+`%direct` is the case where we simply have the data directly. `q` is the
883+data itself, and `r` is any preprocessing instructions. These almost
884+always come from the creation of a file.
885+
886+`%indirect` is both of the preceding cases at once. `q` is the direct
887+data, `r` is the delta, and `s` is the parent blob. It should always be
888+the case that applying `r` to `s` gives the same data as `q` directly
889+(with the prepreprocessor instructions in `p.r`). This exists purely for
890+performance reasons. This is unused, at the moment, but in general these
891+should be created when there are a long line of changes so that we do
892+not have to traverse the delta chain back to the creation of the file.
893+
894+#### `++udon`, abstract delta
895+
896+```hoon
897+ ++ udon :: abstract delta
898+ $: p=umph :: preprocessor
899+ $= q :: patch
900+ $% [%a p=* q=*] :: trivial replace
901+ [%b p=udal] :: atomic indel
902+ [%c p=(urge)] :: list indel
903+ [%d p=upas q=upas] :: tree edit
904+ == ::
905+ == ::
906+```
907+
908+This is an abstract change to a file. This is a superset of what would
909+normally be called diffs. Diffs usually refer to changes in lines of
910+text while we have the ability to do more interesting deltas on
911+arbitrary data structures.
912+
913+`p` is any preprocessor instructions.
914+
915+`%a` refers to the trival delta of a complete replace of old data with
916+new data.
917+
918+`%b` refers to changes in an opaque atom on the block level. This has
919+very limited usefulness, and is not used at the moment.
920+
921+`%c` refers to changes in a list of data. This is often lines of text,
922+which is your classic diff. We, however, will work on any list of data.
923+
924+`%d` refers to changes in a tree of data. This is general enough to
925+describe changes to any hoon noun, but often more special-purpose delta
926+should be created for different content types. This is not used at the
927+moment, and may in fact be unimplemented.
928+
929+#### `++urge`, list change
930+
931+```hoon
932+ ++ urge |*(a=_,* (list (unce a))) :: list change
933+```
934+
935+This is a parametrized type for list changes. For example, `(urge ,@t)`
936+is a list change for lines of text.
937+
938+#### `++unce`, change part of a list.
939+
940+```hoon
941+ ++ unce |* a=_,* :: change part
942+ $% [%& p=@ud] :: skip[copy]
943+ [%| p=(list a) q=(list a)] :: p -> q[chunk]
944+ == ::
945+```
946+
947+This is a single change in a list of elements of type `a`. For example,
948+`(unce ,@t)` is a single change in a lines of text.
949+
950+`%&` means the next `p` lines are unchanged.
951+
952+`%|` means the lines `p` have changed to `q`.
953+
954+#### `++umph`, preprocessing information
955+
956+```hoon
957+ ++ umph :: change filter
958+ $| $? %a :: no filter
959+ %b :: jamfile
960+ %c :: LF text
961+ == ::
962+ $% [%d p=@ud] :: blocklist
963+ == ::
964+```
965+
966+This space intentionally left undocumented. This stuff will change once
967+we get a well-typed clay.
968+
969+#### `++upas`, tree change
970+
971+```hoon
972+ ++ upas :: tree change (%d)
973+ $& [p=upas q=upas] :: cell
974+ $% [%0 p=axis] :: copy old
975+ [%1 p=*] :: insert new
976+ [%2 p=axis q=udon] :: mutate!
977+ == ::
978+```
979+
980+This space intentionally left undocumented. This stuff is not known to
981+work, and will likely change when we get a well-typed clay. Also, this
982+is not a complicated type; it is not difficult to work out the meaning.
983+
984+#### `++nori:clay`, repository action
985+
986+```hoon
987+ ++ nori :: repository action
988+ $% [& q=soba] :: delta
989+ [| p=@tas] :: label
990+ == ::
991+```
992+
993+This describes a change that we are asking clay to make to the desk.
994+There are two kinds of changes that may be made: we can modify files or
995+we can apply a label to a commit.
996+
997+In the `|` case, we will simply label the current commit with the given
998+label. In the `&` case, we will apply the given changes.
999+
1000+#### `++soba:clay`, delta
1001+
1002+```hoon
1003+ ++ soba ,[p=cart q=(list ,[p=path q=miso])] :: delta
1004+```
1005+
1006+This describes a set of changes to make to a desk. The `cart` is simply
1007+a pair of the old hash and the new hash of the desk. The list is a list
1008+of changes keyed by the file they're changing. Thus, the paths are paths
1009+to files to be changed while `miso` is a description of the change
1010+itself.
1011+
1012+#### `++miso:clay`, ankh delta
1013+
1014+```hoon
1015+ ++ miso :: ankh delta
1016+ $% [%del p=*] :: delete
1017+ [%ins p=*] :: insert
1018+ [%mut p=udon] :: mutate
1019+ == ::
1020+```
1021+
1022+There are three kinds of changes that may be made to a node in a desk.
1023+We can insert a file, in which case `p` is the contents of the new file.
1024+We can delete a file, in which case `p` is the contents of the old file.
1025+Finally, we can mutate that file, in which case the `udon` describes the
1026+changes we are applying to the file.
1027+
1028+#### `++mizu:clay`, merged state
1029+
1030+```hoon
1031+ ++ mizu ,[p=@u q=(map ,@ud tako) r=rang] :: new state
1032+```
1033+
1034+This is the input to the `%merg` kiss, which allows us to perform a
1035+merge. The `p` is the number of the new head commit. The `q` is a map
1036+from numbers to commit hashes. This is all the new numbered commits that
1037+are to be inserted. The keys to this should always be the numbers from
1038+`let.dom` plus one to `p`, inclusive. The `r` is the maps of all the new
1039+commits and data. Since these are merged into the current state, no old
1040+commits or data need be here.
1041+
1042+#### `++riff:clay`, request/desist
1043+
1044+```hoon
1045+ ++ riff ,[p=desk q=(unit rave)] :: request/desist
1046+```
1047+
1048+This represents a request for data about a particular desk. If `q`
1049+contains a `rave`, then this opens a subscription to the desk for that
1050+data. If `q` is null, then this tells clay to cancel the subscription
1051+along this duct.
1052+
1053+#### `++riot:clay`, response
1054+
1055+```hoon
1056+ ++ riot (unit rant) :: response/complete
1057+```
1058+
1059+A riot is a response to a subscription. If null, the subscription has
1060+been completed, and no more responses will be sent. Otherwise, the
1061+`rant` is the produced data.
1062+
1063+#### `++rant:clay`, response data
1064+
1065+```hoon
1066+ ++ rant :: namespace binding
1067+ $: p=[p=care q=case r=@tas] :: clade release book
1068+ q=path :: spur
1069+ r=* :: data
1070+ == ::
1071+```
1072+
1073+This is the data at a particular node in the filesystem. `p.p` specifies
1074+the type of data that was requested (and is produced). `q.p` gives the
1075+specific version reported (since a range of versions may be requested in
1076+a subscription). `r.p` is the desk. `q` is the path to the filesystem
1077+node. `r` is the data itself (in the format specified by `p.p`).
1078+
1079+### `++nako`, subscription response data
1080+
1081+```hoon
1082+ ++ nako $: gar=(map ,@ud tako) :: new ids
1083+ let=@ud :: next id
1084+ lar=(set yaki) :: new commits
1085+ bar=(set blob) :: new content
1086+ == ::
1087+```
1088+
1089+This is the data that is produced by a request for a range of revisions
1090+of a desk. This allows us to easily keep track of a remote repository --
1091+all the new information we need is contained in the `nako`.
1092+
1093+`gar` is a map of the revisions in the range to the hash of the commit
1094+at that revision. These hashes can be used with `hut:rang:clay` to find the
1095+commit itself.
1096+
1097+`let` is either the last revision number in the range or the most recent
1098+revision number, whichever is smaller.
1099+
1100+`lar` is the set of new commits, and `bar` is the set of new content.
1101+
1102+## Public Interface
1103+
1104+As with all vanes, there are exactly two ways to interact with clay.
1105+`%clay` exports a namespace accessible through `.^`, which is described
1106+above under `++care:clay`. The primary way of interacting with clay, though,
1107+is by sending kisses and receiving gifts.
1108+
1109+```hoon
1110+ ++ gift :: out result <-$
1111+ $% [%ergo p=@p q=@tas r=@ud] :: version update
1112+ [%note p=@tD q=tank] :: debug message
1113+ [%writ p=riot] :: response
1114+ == ::
1115+ ++ kiss :: in request ->$
1116+ $% [%info p=@p q=@tas r=nori] :: internal edit
1117+ [%ingo p=@p q=@tas r=nori] :: internal noun edit
1118+ [%init p=@p] :: report install
1119+ [%into p=@p q=@tas r=nori] :: external edit
1120+ [%invo p=@p q=@tas r=nori] :: external noun edit
1121+ [%merg p=@p q=@tas r=mizu] :: internal change
1122+ [%wart p=sock q=@tas r=path s=*] :: network request
1123+ [%warp p=sock q=riff] :: file request
1124+ == ::
1125+```
1126+
1127+There are only a small number of possible kisses, so it behooves us to
1128+describe each in detail.
1129+
1130+```hoon
1131+ $% [%info p=@p q=@tas r=nori] :: internal edit
1132+
1133+ [%into p=@p q=@tas r=nori] :: external edit
1134+```
1135+
1136+These two kisses are nearly identical. At a high level, they apply
1137+changes to the filesystem. Whenever we add, remove, or edit a file, one
1138+of these cards is sent. The `p` is the ship whose filesystem we're
1139+trying to change, the `q` is the desk we're changing, and the `r` is the
1140+request change. For the format of the requested change, see the
1141+documentation for `++nori:clay` above.
1142+
1143+When a file is changed in the unix filesystem, vere will send a `%into`
1144+kiss. This tells clay that the duct over which the kiss was sent is the
1145+duct that unix is listening on for changes. From within Arvo, though, we
1146+should never send a `%into` kiss. The `%info` kiss is exactly identical
1147+except it does not reset the duct.
1148+
1149+```hoon
1150+ [%ingo p=@p q=@tas r=nori] :: internal noun edit
1151+
1152+ [%invo p=@p q=@tas r=nori] :: external noun edit
1153+```
1154+
1155+These kisses are currently identical to `%info` and `%into`, though this
1156+will not always be the case. The intent is for these kisses to allow
1157+typed changes to clay so that we may store typed data. This is currently
1158+unimplemented.
1159+
1160+```hoon
1161+ [%init p=@p] :: report install
1162+```
1163+
1164+Init is called when a ship is started on our pier. This simply creates a
1165+default `room` to go into our `raft`. Essentially, this initializes the
1166+filesystem for a ship.
1167+
1168+```hoon
1169+ [%merg p=@p q=@tas r=mizu] :: internal change
1170+```
1171+
1172+This is called to perform a merge. This is most visibly called by
1173+:update to update the filesystem of the current ship to that of its
1174+sein. The `p` and `q` are as in `%info`, and the `r` is the description
1175+of the merge. See `++mizu:clay` above.
1176+
1177+XX
1178+`XX [%wake ~] :: timer activate XX`
1179+XX\
1180+XX This card is sent by unix at the time specified by `++doze`. This
1181+time is XX usually the closest time specified in a subscription request.
1182+When `%wake` is XX called, we update our subscribers if there have been
1183+any changes.
1184+
1185+```hoon
1186+ [%wart p=sock q=@tas r=path s=*] :: network request
1187+```
1188+
1189+This is a request that has come across the network for a particular
1190+file. When another ship asks for a file from us, that request comes to
1191+us in the form of a `%wart` kiss. This is handled by trivially turning
1192+it into a `%warp`.
1193+
1194+```hoon
1195+ [%warp p=sock q=riff] :: file request
1196+```
1197+
1198+This is a request for information about a particular desk. This is, in
1199+its most general form, a subscription, though in many cases it is the
1200+trivial case of a subscription -- a read. See `++riff:clay` for the format of
1201+the request.
1202+
1203+## Lifecycle of a Local Read
1204+
1205+There are two real types of interaction with a filesystem: you can read,
1206+and you can write. We'll describe each process, detailing both the flow
1207+of control followed by the kernel and the algorithms involved. The
1208+simpler case is that of the read, so we'll begin with that.
1209+
1210+When a vane or an application wishes to read a file from the filesystem,
1211+it sends a `%warp` kiss, as described above. Of course, you may request
1212+a file on another ship and, being a global filesystem, clay will happily
1213+produce it for you. That code pathway will be described in another
1214+section; here, we will restrict ourselves to examining the case of a
1215+read from a ship on our own pier.
1216+
1217+The kiss can request either a single version of a file node or a range
1218+of versions of a desk. Here, we'll deal only with a request for a single
1219+version.
1220+
1221+As in all vanes, a kiss enters clay via a call to `++call`. Scanning
1222+through the arm, we quickly see where `%warp` is handled.
1223+
1224+```hoon
1225+ ?: =(p.p.q.hic q.p.q.hic)
1226+ =+ une=(un p.p.q.hic now ruf)
1227+ =+ wex=(di:une p.q.q.hic)
1228+ =+ ^= wao
1229+ ?~ q.q.q.hic
1230+ (ease:wex hen)
1231+ (eave:wex hen u.q.q.q.hic)
1232+ =+ ^= woo
1233+ abet:wao
1234+ [-.woo abet:(pish:une p.q.q.hic +.woo ran.wao)]
1235+```
1236+
1237+We're following the familar patern of producing a list of moves and an
1238+updated state. In this case, the state is `++raft`.
1239+
1240+We first check to see if the sending and receiving ships are the same.
1241+If they're not, then this is a request for data on another ship. We
1242+describe that process later. Here, we discuss only the case of a local
1243+read.
1244+
1245+At a high level, the call to `++un` sets up the core for the domestic
1246+ship that contains the files we're looking for. The call to `++di` sets
1247+up the core for the particular desk we're referring to.
1248+
1249+After this, we perform the actual request. If there is no rave in the
1250+riff, then that means we are cancelling a request, so we call
1251+`++ease:de`. Otherwise, we start a subscription with `++eave:de`. We
1252+call `++abet:de` to resolve our various types of output into actual
1253+moves. We produce the moves we found above and the `++un` core resolved
1254+with `++pish:un` (putting the modified desk in the room) and `++abet:un`
1255+(putting the modified room in the raft).
1256+
1257+Much of this is fairly straightforward, so we'll only describe `++ease`,
1258+`++eave`, and `++abet:de`. Feel free to look up the code to the other
1259+steps -- it should be easy to follow.
1260+
1261+Although it's called last, it's usually worth examining `++abet` first,
1262+since it defines in what ways we can cause side effects. Let's do that,
1263+and also a few of the lines at the beginning of `++de`.
1264+
1265+```hoon
1266+ =| yel=(list ,[p=duct q=gift])
1267+ =| byn=(list ,[p=duct q=riot])
1268+ =| vag=(list ,[p=duct q=gift])
1269+ =| say=(list ,[p=duct q=path r=ship s=[p=@ud q=riff]])
1270+ =| tag=(list ,[p=duct q=path c=note])
1271+ |%
1272+ ++ abet
1273+ ^- [(list move) rede]
1274+ :_ red
1275+ ;: weld
1276+ %+ turn (flop yel)
1277+ |=([a=duct b=gift] [hun %give b])
1278+ ::
1279+ %+ turn (flop byn)
1280+ |=([a=duct b=riot] [a %give [%writ b]])
1281+ ::
1282+ %+ turn (flop vag)
1283+ |=([a=duct b=gift] [a %give b])
1284+ ::
1285+ %+ turn (flop say)
1286+ |= [a=duct b=path c=ship d=[p=@ud q=riff]]
1287+ :- a
1288+ [%pass b %a %want [who c] [%q %re p.q.d (scot %ud p.d) ~] q.d]
1289+ ::
1290+ %+ turn (flop tag)
1291+ |=([a=duct b=path c=note] [a %pass b c])
1292+ ==
1293+```
1294+
1295+This is very simple code. We see there are exactly five different kinds
1296+of side effects we can generate.
1297+
1298+In `yel` we put gifts that we wish to be sent along the `hun:room` duct
1299+to dill. See the documentation for `++room` above. This is how we
1300+display messages to the terminal.
1301+
1302+In `byn` we put riots that we wish returned to subscribers. Recall that
1303+a riot is a response to a subscription. These are returned to our
1304+subscribers in the form of a `%writ` gift.
1305+
1306+In `vag` we put gifts along with the ducts on which to send them. This
1307+allows us to produce arbitrary gifts, but in practice this is only used
1308+to produce `%ergo` gifts.
1309+
1310+In `say` we put messages we wish to pass to ames. These messages are
1311+used to request information from clay on other piers. We must provide
1312+not only the duct and the request (the riff), but also the return path,
1313+the other ship to talk to, and the sequence number of the request.
1314+
1315+In `tag` we put arbitrary notes we wish to pass to other vanes. For now,
1316+the only notes we pass here are `%wait` and `%rest` to the timer vane.
1317+
1318+Now that we know what kinds of side effects we may have, we can jump
1319+into the handling of requests.
1320+
1321+```hoon
1322+ ++ ease :: release request
1323+ |= hen=duct
1324+ ^+ +>
1325+ ?~ ref +>
1326+ =+ rov=(~(got by qyx) hen)
1327+ =. qyx (~(del by qyx) hen)
1328+ (mabe rov (cury best hen))
1329+ =. qyx (~(del by qyx) hen)
1330+ |- ^+ +>+.$
1331+ =+ nux=(~(get by fod.u.ref) hen)
1332+ ?~ nux +>+.$
1333+ %= +>+.$
1334+ say [[hen [(scot %ud u.nux) ~] for [u.nux syd ~]] say]
1335+ fod.u.ref (~(del by fod.u.ref) hen)
1336+ bom.u.ref (~(del by bom.u.ref) u.nux)
1337+ ==
1338+```
1339+
1340+This is called when we're cancelling a subscription. For domestic desks,
1341+`ref` is null, so we're going to cancel any timer we might have created.
1342+We first delete the duct from our map of requests, and then we call
1343+`++mabe` with `++best` to send a `%rest` kiss to the timer vane if we
1344+have started a timer. We'll describe `++best` and `++mabe` momentarily.
1345+
1346+Although we said we're not going to talk about foreign requests yet,
1347+it's easy to see that for foreign desks, we cancel any outstanding
1348+requests for this duct and send a message over ames to the other ship
1349+telling them to cancel the subscription.
1350+
1351+```hoon
1352+ ++ best
1353+ |= [hen=duct tym=@da]
1354+ %_(+> tag :_(tag [hen /tyme %t %rest tym]))
1355+```
1356+
1357+This simply pushes a `%rest` note onto `tag`, from where it will be
1358+passed back to arvo to be handled. This cancels the timer at the given
1359+duct (with the given time).
1360+
1361+```hoon
1362+ ++ mabe :: maybe fire function
1363+ |* [rov=rove fun=$+(@da _+>.^$)]
1364+ ^+ +>.$
1365+ %- fall :_ +>.$
1366+ %- bind :_ fun
1367+ ^- (unit ,@da)
1368+ ?- -.rov
1369+ %&
1370+ ?. ?=(%da -.q.p.rov) ~
1371+ `p.q.p.rov
1372+ %|
1373+ =* mot p.rov
1374+ %+ hunt
1375+ ?. ?=(%da -.p.mot) ~
1376+ ?.((lth now p.p.mot) ~ [~ p.p.mot])
1377+ ?. ?=(%da -.q.mot) ~
1378+ ?.((lth now p.q.mot) [~ now] [~ p.q.mot])
1379+ ==
1380+```
1381+
1382+This decides whether the given request can only be satsified in the
1383+future. In that case, we call the given function with the time in the
1384+future when we expect to have an update to give to this request. This is
1385+called with `++best` to cancel timers and with `++bait` to start them.
1386+
1387+For single requests, we have a time if the request is for a particular
1388+time (which is assumed to be in the future). For ranges of requests, we
1389+check both the start and end cases to see if they are time cases. If so,
1390+we choose the earlier time.
1391+
1392+If any of those give us a time, then we call the given funciton with the
1393+smallest time.
1394+
1395+The more interesting case is, of course, when we're not cancelling a
1396+subscription but starting one.
1397+
1398+```hoon
1399+ ++ eave :: subscribe
1400+ |= [hen=duct rav=rave]
1401+ ^+ +>
1402+ ?- -.rav
1403+ &
1404+ ?: &(=(p.p.rav %u) !=(p.q.p.rav now))
1405+ ~& [%clay-fail p.q.p.rav %now now]
1406+ !!
1407+ =+ ver=(aver p.rav)
1408+ ?~ ver
1409+ (duce hen rav)
1410+ ?~ u.ver
1411+ (blub hen)
1412+ (blab hen p.rav u.u.ver)
1413+```
1414+
1415+There are two types of subscriptions -- either we're requesting a single
1416+file or we're requesting a range of versions of a desk. We'll dicuss the
1417+simpler case first.
1418+
1419+First, we check that we're not requesting the `rang` from any time other
1420+than the present. Since we don't store that information for any other
1421+time, we can't produce it in a referentially transparent manner for any
1422+time other than the present.
1423+
1424+Then, we try to read the requested `mood:clay` `p.rav`. If we can't access
1425+the request data right now, we call `++duce` to put the request in our
1426+queue to be satisfied when the information becomes available.
1427+
1428+This case occurs when we make a request for a case whose (1) date is
1429+after the current date, (2) number is after the current number, or (3)
1430+label is not yet used.
1431+
1432+```hoon
1433+ ++ duce :: produce request
1434+ |= [hen=duct rov=rove]
1435+ ^+ +>
1436+ =. qyx (~(put by qyx) hen rov)
1437+ ?~ ref
1438+ (mabe rov (cury bait hen))
1439+ |- ^+ +>+.$ :: XX why?
1440+ =+ rav=(reve rov)
1441+ =+ ^= vaw ^- rave
1442+ ?. ?=([%& %v *] rav) rav
1443+ [%| [%ud let.dom] `case`q.p.rav r.p.rav]
1444+ =+ inx=nix.u.ref
1445+ %= +>+.$
1446+ say [[hen [(scot %ud inx) ~] for [inx syd ~ vaw]] say]
1447+ nix.u.ref +(nix.u.ref)
1448+ bom.u.ref (~(put by bom.u.ref) inx [hen vaw])
1449+ fod.u.ref (~(put by fod.u.ref) hen inx)
1450+ ==
1451+```
1452+
1453+The code for `++duce` is nearly the exact inverse of `++ease`, which in
1454+the case of a domestic desk is very simple -- we simply put the duct and
1455+rave into `qyx` and possibly start a timer with `++mabe` and `++bait`.
1456+Recall that `ref` is null for domestic desks and that `++mabe` fires the
1457+given function with the time we need to be woken up at, if we need to be
1458+woken up at a particular time.
1459+
1460+```hoon
1461+ ++ bait
1462+ |= [hen=duct tym=@da]
1463+ %_(+> tag :_(tag [hen /tyme %t %wait tym]))
1464+```
1465+
1466+This sets an alarm by sending a `%wait` card with the given time to the
1467+timer vane.
1468+
1469+Back in `++eave`, if `++aver` returned `[~ ~]`, then we cancel the
1470+subscription. This occurs when we make (1) a `%x` request for a file
1471+that does not exist, (2) a `%w` request with a case that is not a
1472+number, or (3) a `%w` request with a nonempty path. The `++blub` is
1473+exactly what you would expect it to be.
1474+
1475+```hoon
1476+ ++ blub :: ship stop
1477+ |= hen=duct
1478+ %_(+> byn [[hen ~] byn])
1479+```
1480+
1481+We notify the duct that we're cancelling their subscription since it
1482+isn't satisfiable.
1483+
1484+Otherwise, we have received the desired information, so we send it on to
1485+the subscriber with `++blab`.
1486+
1487+```hoon
1488+ ++ blab :: ship result
1489+ |= [hen=duct mun=mood dat=*]
1490+ ^+ +>
1491+ +>(byn [[hen ~ [p.mun q.mun syd] r.mun dat] byn])
1492+```
1493+
1494+The most interesting arm called in `++eave` is, of course, `++aver`,
1495+where we actually try to read the data.
1496+
1497+```hoon
1498+ ++ aver :: read
1499+ |= mun=mood
1500+ ^- (unit (unit ,*))
1501+ ?: &(=(p.mun %u) !=(p.q.mun now)) :: prevent bad things
1502+ ~& [%clay-fail p.q.mun %now now]
1503+ !!
1504+ =+ ezy=?~(ref ~ (~(get by haw.u.ref) mun))
1505+ ?^ ezy ezy
1506+ =+ nao=(~(case-to-aeon ze lim dom ran) q.mun)
1507+ ?~(nao ~ [~ (~(read-at-aeon ze lim dom ran) u.nao mun)])
1508+```
1509+
1510+We check immediately that we're not requesting the `rang` for any time
1511+other than the present.
1512+
1513+If this is a foreign desk, then we check our cache for the specific
1514+request. If either this is a domestic desk or we don't have the request
1515+in our cache, then we have to actually go read the data from our dome.
1516+
1517+We need to do two things. First, we try to find the number of the commit
1518+specified by the given case, and then we try to get the data there.
1519+
1520+Here, we jump into `arvo/zuse.hoon`, which is where much of the
1521+algorithmic code is stored, as opposed to the clay interface, which is
1522+stored in `arvo/clay.hoon`. We examine `++case-to-aeon:ze`.
1523+
1524+```hoon
1525+ ++ case-to-aeon :: case-to-aeon:ze
1526+ |= lok=case :: act count through
1527+ ^- (unit aeon)
1528+ ?- -.lok
1529+ %da
1530+ ?: (gth p.lok lim) ~
1531+ |- ^- (unit aeon)
1532+ ?: =(0 let) [~ 0] :: avoid underflow
1533+ ?: %+ gte p.lok
1534+ =< t
1535+ %- tako-to-yaki
1536+ %- aeon-to-tako
1537+ let
1538+ [~ let]
1539+ $(let (dec let))
1540+ ::
1541+ %tas (~(get by lab) p.lok)
1542+ %ud ?:((gth p.lok let) ~ [~ p.lok])
1543+ ==
1544+```
1545+
1546+We handle each type of `case:clay` differently. The latter two types are
1547+easy.
1548+
1549+If we're requesting a revision by label, then we simply look up the
1550+requested label in `lab` from the given dome. If it exists, that is our
1551+aeon; else we produce null, indicating the requested revision does not
1552+yet exist.
1553+
1554+If we're requesting a revision by number, we check if we've yet reached
1555+that number. If so, we produce the number; else we produce null.
1556+
1557+If we're requesting a revision by date, we check first if the date is in
1558+the future, returning null if so. Else we start from the most recent
1559+revision and scan backwards until we find the first revision committed
1560+before that date, and we produce that. If we requested a date before any
1561+revisions were committed, we produce `0`.
1562+
1563+The definitions of `++aeon-to-tako` and `++tako-to-yaki` are trivial.
1564+
1565+```hoon
1566+ ++ aeon-to-tako ~(got by hit)
1567+
1568+ ++ tako-to-yaki ~(got by hut) :: grab yaki
1569+```
1570+
1571+We simply look up the aeon or tako in their respective maps (`hit` and
1572+`hut`).
1573+
1574+Assuming we got a valid version number, `++aver` calls
1575+`++read-at-aeon:ze`, which reads the requested data at the given
1576+revision.
1577+
1578+```hoon
1579+ ++ read-at-aeon :: read-at-aeon:ze
1580+ |= [oan=aeon mun=mood] :: seek and read
1581+ ^- (unit)
1582+ ?: &(?=(%w p.mun) !?=(%ud -.q.mun)) :: NB only for speed
1583+ ?^(r.mun ~ [~ oan])
1584+ (read:(rewind oan) mun)
1585+```
1586+
1587+If we're requesting the revision number with a case other than by
1588+number, then we go ahead and just produce the number we were given.
1589+Otherwise, we call `++rewind` to rewind our state to the given revision,
1590+and then we call `++read` to get the requested information.
1591+
1592+```hoon
1593+ ++ rewind :: rewind:ze
1594+ |= oan=aeon :: rewind to aeon
1595+ ^+ +>
1596+ ?: =(let oan) +>
1597+ ?: (gth oan let) !! :: don't have version
1598+ +>(ank (checkout-ankh q:(tako-to-yaki (aeon-to-tako oan))), let oan)
1599+```
1600+
1601+If we're already at the requested version, we do nothing. If we're
1602+requesting a version later than our head, we are unable to comply.
1603+
1604+Otherwise, we get the hash of the commit at the number, and from that we
1605+get the commit itself (the yaki), which has the map of path to lobe that
1606+represents a version of the filesystem. We call `++checkout-ankh` to
1607+checkout the commit, and we replace `ank` in our context with the
1608+result.
1609+
1610+```hoon
1611+ ++ checkout-ankh :: checkout-ankh:ze
1612+ |= hat=(map path lobe) :: checkout commit
1613+ ^- ankh
1614+ %- cosh
1615+ %+ roll (~(tap by hat) ~)
1616+ |= [[pat=path bar=lobe] ank=ankh]
1617+ ^- ankh
1618+ %- cosh
1619+ ?~ pat
1620+ =+ zar=(lobe-to-noun bar)
1621+ ank(q [~ (sham zar) zar])
1622+ =+ nak=(~(get by r.ank) i.pat)
1623+ %= ank
1624+ r %+ ~(put by r.ank) i.pat
1625+ $(pat t.pat, ank (fall nak _ankh))
1626+ ==
1627+```
1628+
1629+Twice we call `++cosh`, which hashes a commit, updating `p` in an
1630+`ankh`. Let's jump into that algorithm before we describe
1631+`++checkout-ankh`.
1632+
1633+```hoon
1634+ ++ cosh :: locally rehash
1635+ |= ank=ankh :: NB v/unix.c
1636+ ank(p rehash:(zu ank))
1637+```
1638+
1639+We simply replace `p` in the hash with the `cash` we get from a call to
1640+`++rehash:zu`.
1641+
1642+```hoon
1643+ ++ zu !: :: filesystem
1644+ |= ank=ankh :: filesystem state
1645+ =| myz=(list ,[p=path q=miso]) :: changes in reverse
1646+ =| ram=path :: reverse path into
1647+ |%
1648+ ++ rehash :: local rehash
1649+ ^- cash
1650+ %+ mix ?~(q.ank 0 p.u.q.ank)
1651+ =+ axe=1
1652+ |- ^- cash
1653+ ?~ r.ank _@
1654+ ;: mix
1655+ (shaf %dash (mix axe (shaf %dush (mix p.n.r.ank p.q.n.r.ank))))
1656+ $(r.ank l.r.ank, axe (peg axe 2))
1657+ $(r.ank r.r.ank, axe (peg axe 3))
1658+ ==
1659+```
1660+
1661+`++zu` is a core we set up with a particular filesystem node to traverse
1662+a checkout of the filesystem and access the actual data inside it. One
1663+of the things we can do with it is to create a recursive hash of the
1664+node.
1665+
1666+In `++rehash`, if this node is a file, then we xor the remainder of the
1667+hash with the hash of the contents of the file. The remainder of the
1668+hash is `0` if we have no children, else we descend into our children.
1669+Basically, we do a half SHA-256 of the xor of the axis of this child and
1670+the half SHA-256 of the xor of the name of the child and the hash of the
1671+child. This is done for each child and all the results are xored
1672+together.
1673+
1674+Now we return to our discussion of `++checkout-ankh`.
1675+
1676+We fold over every path in this version of the filesystem and create a
1677+great ankh out of them. First, we call `++lobe-to-noun` to get the raw
1678+data referred to be each lobe.
1679+
1680+```hoon
1681+ ++ lobe-to-noun :: grab blob
1682+ |= p=lobe :: ^- *
1683+ %- blob-to-noun
1684+ (lobe-to-blob p)
1685+```
1686+
1687+This converts a lobe into the raw data it refers to by first getting the
1688+blob with `++lobe-to-blob` and converting that into data with
1689+`++blob-to-noun`.
1690+
1691+```hoon
1692+ ++ lobe-to-blob ~(got by lat) :: grab blob
1693+```
1694+
1695+This just grabs the blob that the lobe refers to.
1696+
1697+```hoon
1698+ ++ blob-to-noun :: grab blob
1699+ |= p=blob
1700+ ?- -.p
1701+ %delta (lump r.p (lobe-to-noun q.p))
1702+ %direct q.p
1703+ %indirect q.p
1704+ ==
1705+```
1706+
1707+If we have either a direct or an indirect blob, then the data is stored
1708+right in the blob. Otherwise, we have to reconstruct it from the diffs.
1709+We do this by calling `++lump` on the diff in the blob with the data
1710+obtained by recursively calling the parent of this blob.
1711+
1712+```hoon
1713+ ++ lump :: apply patch
1714+ |= [don=udon src=*]
1715+ ^- *
1716+ ?+ p.don ~|(%unsupported !!)
1717+ %a
1718+ ?+ -.q.don ~|(%unsupported !!)
1719+ %a q.q.don
1720+ %c (lurk ((hard (list)) src) p.q.don)
1721+ %d (lure src p.q.don)
1722+ ==
1723+ ::
1724+ %c
1725+ =+ dst=(lore ((hard ,@) src))
1726+ %- roly
1727+ ?+ -.q.don ~|(%unsupported !!)
1728+ %a ((hard (list ,@t)) q.q.don)
1729+ %c (lurk dst p.q.don)
1730+ ==
1731+ ==
1732+```
1733+
1734+This is defined in `arvo/hoon.hoon` for historical reasons which are
1735+likely no longer applicable. Since the `++umph` structure will likely
1736+change we convert clay to be a typed filesystem, we'll only give a
1737+high-level description of this process. If we have a `%a` udon, then
1738+we're performing a trivial replace, so we produce simply `q.q.don`. If
1739+we have a `%c` udon, then we're performing a list merge (as in, for
1740+example, lines of text). The merge is performed by `++lurk`.
1741+
1742+```hoon
1743+ ++ lurk :: apply list patch
1744+ |* [hel=(list) rug=(urge)]
1745+ ^+ hel
1746+ =+ war=`_hel`~
1747+ |- ^+ hel
1748+ ?~ rug (flop war)
1749+ ?- -.i.rug
1750+ &
1751+ %= $
1752+ rug t.rug
1753+ hel (slag p.i.rug hel)
1754+ war (weld (flop (scag p.i.rug hel)) war)
1755+ ==
1756+ ::
1757+ |
1758+ %= $
1759+ rug t.rug
1760+ hel =+ gur=(flop p.i.rug)
1761+ |- ^+ hel
1762+ ?~ gur hel
1763+ ?>(&(?=(^ hel) =(i.gur i.hel)) $(hel t.hel, gur t.gur))
1764+ war (weld q.i.rug war)
1765+ ==
1766+ ==
1767+```
1768+
1769+We accumulate our final result in `war`. If there's nothing more in our
1770+list of merge instructions (unces), we just reverse `war` and produce
1771+it. Otherwise, we process another unce. If the unce is of type `&`, then
1772+we have `p.i.rug` lines of no changes, so we just copy them over from
1773+`hel` to `war`. If the unice is of type `|`, then we verify that the
1774+source lines (in `hel`) are what we expect them to be (`p.i.rug`),
1775+crashing on failure. If they're good, then we append the new lines in
1776+`q.i.rug` onto `war`.
1777+
1778+And that's really it. List merges are pretty easy. Anyway, if you
1779+recall, we were discussing `++checkout-ankh`.
1780+
1781+```hoon
1782+ ++ checkout-ankh :: checkout-ankh:ze
1783+ |= hat=(map path lobe) :: checkout commit
1784+ ^- ankh
1785+ %- cosh
1786+ %+ roll (~(tap by hat) ~)
1787+ |= [[pat=path bar=lobe] ank=ankh]
1788+ ^- ankh
1789+ %- cosh
1790+ ?~ pat
1791+ =+ zar=(lobe-to-noun bar)
1792+ ank(q [~ (sham zar) zar])
1793+ =+ nak=(~(get by r.ank) i.pat)
1794+ %= ank
1795+ r %+ ~(put by r.ank) i.pat
1796+ $(pat t.pat, ank (fall nak _ankh))
1797+ ==
1798+```
1799+
1800+If the path is null, then we calculate `zar`, the raw data at the path
1801+`pat` in this version. We produce the given ankh with the correct data.
1802+
1803+Otherwise, we try to get the child we're looking at from our parent
1804+ankh. If it's already been created, this succeeds; otherwise, we simply
1805+create a default blank ankh. We place ourselves in our parent after
1806+recursively computing our children.
1807+
1808+This algorithm really isn't that complicated, but it may not be
1809+immediately obvious why it works. An example should clear everything up.
1810+
1811+Suppose `hat` is a map of the following information.
1812+
1813+```
1814+ /greeting --> "customary upon meeting"
1815+ /greeting/english --> "hello"
1816+ /greeting/spanish --> "hola"
1817+ /greeting/russian/short --> "привет"
1818+ /greeting/russian/long --> "Здравствуйте"
1819+ /farewell/russian --> "до свидания"
1820+```
1821+
1822+Furthermore, let's say that we process them in this order:
1823+
1824+```
1825+ /greeting/english
1826+ /greeting/russian/short
1827+ /greeting/russian/long
1828+ /greeting
1829+ /greeting/spanish
1830+ /farewell/russian
1831+```
1832+
1833+Then, the first path we process is `/greeting/english` . Since our path
1834+is not null, we try to get `nak`, but because our ankh is blank at this
1835+point it doesn't find anything. Thus, update our blank top-level ankh
1836+with a child `%greeting`. and recurse with the blank `nak` to create the
1837+ankh of the new child.
1838+
1839+In the recursion, we our path is `/english` and our ankh is again blank.
1840+We try to get the `english` child of our ankh, but this of course fails.
1841+Thus, we update our blank `/greeting` ankh with a child `english`
1842+produced by recursing.
1843+
1844+Now our path is null, so we call `++lobe-to-noun` to get the actual
1845+data, and we place it in the brand-new ankh.
1846+
1847+Next, we process `/greeting/russian/short`. Since our path is not null,
1848+we try to get the child named `%greeting`, which does exist since we
1849+created it earlier. We put modify this child by recursing on it. Our
1850+path is now `/russian/short`, so we look for a `%russian` child in our
1851+`/greeting` ankh. This doesn't exist, so we add it by recursing. Our
1852+path is now `/short`, so we look for a `%short` child in our
1853+`/greeting/russian` ankh. This doesn't exist, so we add it by recursing.
1854+Now our path is null, so we set the contents of this node to `"привет"`,
1855+and we're done processing this path.
1856+
1857+Next, we process `/greeting/russian/long`. This proceeds similarly to
1858+the previous except that now the ankh for `/greeting/russian` already
1859+exists, so we simply reuse it rather than creating a new one. Of course,
1860+we still must create a new `/greeting/russian/long` ankh.
1861+
1862+Next, we process `/greeting`. This ankh already exists, so after we've
1863+recursed once, our path is null, and our ankh is not blank -- it already
1864+has two children (and two grandchildren). We don't touch those, though,
1865+since a node may be both a file and a directory. We just add the
1866+contents of the file -- "customary upon meeting" -- to the existing
1867+ankh.
1868+
1869+Next, we process `/greeting/spanish`. Of course, the `/greeting` ankh
1870+already exists, but it doesn't have a `%spanish` child, so we create
1871+that, taking care not to disturb the contents of the `/greeting` file.
1872+We put "hola" into the ankh and call it good.
1873+
1874+Finally, we process `/farewell/russian`. Here, the `/farewell` ankh
1875+doesn't exist, so we create it. Clearly the newly-created ankh doesn't
1876+have any children, so we have to add a `%russian` child, and in this
1877+child we put our last content -- "до свидания".
1878+
1879+We hope it's fairly obvious that the order we process the paths doesn't
1880+affect the final ankh tree. The tree will be constructed in a very
1881+different order depending on what order the paths come in, but the
1882+resulting tree is independent of order.
1883+
1884+At any rate, we were talking about something important, weren't we? If
1885+you recall, that concludes our discussion of `++rewind`, which was
1886+called from `++read-at-aeon`. In summary, `++rewind` returns a context
1887+in which our current state is (very nearly) as it was when the specified
1888+version of the desk was the head. This allows `++read-at-aeon` to call
1889+`++read` to read the requested information.
1890+
1891+```hoon
1892+ ++ read :: read:ze
1893+ |= mun=mood :: read at point
1894+ ^- (unit)
1895+ ?: ?=(%v p.mun)
1896+ [~ `dome`+<+<.read]
1897+ ?: &(?=(%w p.mun) !?=(%ud -.q.mun))
1898+ ?^(r.mun ~ [~ let])
1899+ ?: ?=(%w p.mun)
1900+ =+ ^= yak
1901+ %- tako-to-yaki
1902+ %- aeon-to-tako
1903+ let
1904+ ?^(r.mun ~ [~ [t.yak (forge-nori yak)]])
1905+ ::?> ?=(^ hit) ?^(r.mun ~ [~ i.hit]) :: what do?? need [@da nori]
1906+ (query(ank ank:(descend-path:(zu ank) r.mun)) p.mun)
1907+```
1908+
1909+If we're requesting the dome, then we just return that immediately.
1910+
1911+If we're requesting the revision number of the desk and we're not
1912+requesting it by number, then we just return the current number of this
1913+desk. Note of course that this was really already handled in
1914+`++read-at-aeon`.
1915+
1916+If we're requesting a `%w` with a specific revision number, then we do
1917+something or other with the commit there. It's kind of weird, and it
1918+doesn't seem to work, so we'll ignore this case.
1919+
1920+Otherwise, we descend into the ankh tree to the given path with
1921+`++descend-path:zu`, and then we handle specific request in `++query`.
1922+
1923+```hoon
1924+ ++ descend-path :: descend recursively
1925+ |= way=path
1926+ ^+ +>
1927+ ?~(way +> $(way t.way, +> (descend i.way)))
1928+```
1929+
1930+This is simple recursion down into the ankh tree. `++descend` descends
1931+one level, so this will eventually get us down to the path we want.
1932+
1933+```hoon
1934+ ++ descend :: descend
1935+ |= lol=@ta
1936+ ^+ +>
1937+ =+ you=(~(get by r.ank) lol)
1938+ +>.$(ram [lol ram], ank ?~(you [*cash ~ ~] u.you))
1939+```
1940+
1941+`ram` is the path that we're at, so to descend one level we push the
1942+name of this level onto that path. We update the ankh with the correct
1943+one at that path if it exists; else we create a blank one.
1944+
1945+Once we've decscended to the correct level, we need to actually deal
1946+with the request.
1947+
1948+```hoon
1949+ ++ query :: query:ze
1950+ |= ren=?(%u %v %x %y %z) :: endpoint query
1951+ ^- (unit ,*)
1952+ ?- ren
1953+ %u [~ `rang`+<+>.query]
1954+ %v [~ `dome`+<+<.query]
1955+ %x ?~(q.ank ~ [~ q.u.q.ank])
1956+ %y [~ as-arch]
1957+ %z [~ ank]
1958+ ==
1959+```
1960+
1961+Now that everything's set up, it's really easy. If they're requesting
1962+the rang, dome, or ankh, we give it to them. If the contents of a file,
1963+we give it to them if it is in fact a file. If the `arch`, then we
1964+calculate it with `++as-arch`.
1965+
1966+```hoon
1967+ ++ as-arch :: as-arch:ze
1968+ ^- arch :: arch report
1969+ :+ p.ank
1970+ ?~(q.ank ~ [~ p.u.q.ank])
1971+ |- ^- (map ,@ta ,~)
1972+ ?~ r.ank ~
1973+ [[p.n.r.ank ~] $(r.ank l.r.ank) $(r.ank r.r.ank)]
1974+```
1975+
1976+This very simply strips out all the "real" data and returns just our own
1977+hash, the hash of the file contents (if we're a file), and a map of the
1978+names of our immediate children.
1979+
1980+## Lifecycle of a Local Subscription
1981+
1982+A subscription to a range of revisions of a desk initially follows the
1983+same path that a single read does. In `++aver`, we checked the head of
1984+the given rave. If the head was `&`, then it was a single request, so we
1985+handled it above. If `|`, then we handle it with the following code.
1986+
1987+```hoon
1988+ =+ nab=(~(case-to-aeon ze lim dom ran) p.p.rav)
1989+ ?~ nab
1990+ ?> =(~ (~(case-to-aeon ze lim dom ran) q.p.rav))
1991+ (duce hen (rive rav))
1992+ =+ huy=(~(case-to-aeon ze lim dom ran) q.p.rav)
1993+ ?: &(?=(^ huy) |((lth u.huy u.nab) &(=(0 u.huy) =(0 u.nab))))
1994+ (blub hen)
1995+ =+ top=?~(huy let.dom u.huy)
1996+ =+ sar=(~(lobes-at-path ze lim dom ran) u.nab r.p.rav)
1997+ =+ ear=(~(lobes-at-path ze lim dom ran) top r.p.rav)
1998+ =. +>.$
1999+ ?: =(sar ear) +>.$
2000+ =+ fud=(~(make-nako ze lim dom ran) u.nab top)
2001+ (bleb hen u.nab fud)
2002+ ?^ huy
2003+ (blub hen)
2004+ =+ ^= ptr ^- case
2005+ [%ud +(let.dom)]
2006+ (duce hen `rove`[%| ptr q.p.rav r.p.rav ear])
2007+ ==
2008+```
2009+
2010+Recall that `++case-to-aeon:ze` produces the revision number that a case
2011+corresponds to, if it corresponds to any. If it doesn't yet correspond
2012+to a revision, then it produces null.
2013+
2014+Thus, we first check to see if we've even gotten to the beginning of the
2015+range of revisions requested. If not, then we assert that we haven't yet
2016+gotten to the end of the range either, because that would be really
2017+strange. If not, then we immediately call `++duce`, which, if you
2018+recall, for a local request, simply puts this duct and rove into our
2019+cult `qyx`, so that we know who to respond to when the revision does
2020+appear.
2021+
2022+If we've already gotten to the first revision, then we can produce some
2023+content immediately. If we've also gotten to the final revision, and
2024+that revision is earlier than the start revision, then it's a bad
2025+request and we call `++blub`, which tells the subscriber that his
2026+subscription will not be satisfied.
2027+
2028+Otherwise, we find the data at the given path at the beginning of the
2029+subscription and at the last available revision in the subscription. If
2030+they're the same, then we don't send a notification. Otherwise, we call
2031+`++gack`, which creates the `++nako` we need to produce. We call
2032+`++bleb` to actually produce the information.
2033+
2034+If we already have the last requested revision, then we also tell the
2035+subscriber with `++blub` that the subscription will receive no further
2036+updates.
2037+
2038+If there will be more revisions in the subscription, then we call
2039+`++duce`, adding the duct to our subscribers. We modify the rove to
2040+start at the next revision since we've already handled all the revisions
2041+up to the present.
2042+
2043+We glossed over the calls to `++lobes-at-path`, `++make-nako`, and
2044+`++bleb`, so we'll get back to those right now. `++bleb` is simple, so
2045+we'll start with that.
2046+
2047+```hoon
2048+ ++ bleb :: ship sequence
2049+ |= [hen=duct ins=@ud hip=nako]
2050+ ^+ +>
2051+ (blab hen [%w [%ud ins] ~] hip)
2052+```
2053+
2054+We're given a duct, the beginning revision number, and the nako that
2055+contains the updates since that revision. We use `++blab` to produce
2056+this result to the subscriber. The case is `%w` with a revision number
2057+of the beginning of the subscription, and the data is the nako itself.
2058+
2059+We call `++lobes-at-path:ze` to get the data at the particular path.
2060+
2061+```hoon
2062+ ++ lobes-at-path :: lobes-at-path:ze
2063+ |= [oan=aeon pax=path] :: data at path
2064+ ^- (map path lobe)
2065+ ?: =(0 oan) ~
2066+ %- mo
2067+ %+ skim
2068+ %. ~
2069+ %~ tap by
2070+ =< q
2071+ %- tako-to-yaki
2072+ %- aeon-to-tako
2073+ oan
2074+ |= [p=path q=lobe]
2075+ ?| ?=(~ pax)
2076+ ?& !?=(~ p)
2077+ =(-.pax -.p)
2078+ $(p +.p, pax +.pax)
2079+ == ==
2080+```
2081+
2082+At revision zero, the theoretical common revision between all
2083+repositories, there is no data, so we produce null.
2084+
2085+We get the list of paths (paired with their lobe) in the revision
2086+referred to by the given number and we keep only those paths which begin
2087+with `pax`. Converting to a map, we now have a map from the subpaths at
2088+the given path to the hash of their data. This is simple and efficient
2089+to calculate and compare to later revisions. This allows us to easily
2090+tell if a node or its children have changed.
2091+
2092+Finally, we will describe `++make-nako:ze`.
2093+
2094+```hoon
2095+ ++ make-nako :: gack a through b
2096+ |= [a=aeon b=aeon]
2097+ ^- [(map aeon tako) aeon (set yaki) (set blob)]
2098+ :_ :- b
2099+ =- [(takos-to-yakis -<) (lobes-to-blobs ->)]
2100+ %+ reachable-between-takos
2101+ (~(get by hit) a) :: if a not found, a=0
2102+ (aeon-to-tako b)
2103+ ^- (map aeon tako)
2104+ %- mo %+ skim (~(tap by hit) ~)
2105+ |= [p=aeon *]
2106+ &((gth p a) (lte p b))
2107+```
2108+
2109+We need to produce four things -- the numbers of the new commits, the
2110+number of the latest commit, the new commits themselves, and the new
2111+data itself.
2112+
2113+The first is fairly easy to produce. We simply go over our map of
2114+numbered commits and produce all those numbered greater than `a` and not
2115+greater than `b`.
2116+
2117+The second is even easier to produce -- `b` is clearly our most recent
2118+commit.
2119+
2120+The third and fourth are slightly more interesting, though not too
2121+terribly difficult. First, we call `++reachable-between-takos`.
2122+
2123+```hoon
2124+ ++ reachable-between-takos
2125+ |= [a=(unit tako) b=tako] :: pack a through b
2126+ ^- [(set tako) (set lobe)]
2127+ =+ ^= sar
2128+ ?~ a ~
2129+ (reachable-takos r:(tako-to-yaki u.a))
2130+ =+ yak=`yaki`(tako-to-yaki b)
2131+ %+ new-lobes-takos (new-lobes ~ sar) :: get lobes
2132+ |- ^- (set tako) :: walk onto sar
2133+ ?: (~(has in sar) r.yak)
2134+ ~
2135+ =+ ber=`(set tako)`(~(put in `(set tako)`~) `tako`r.yak)
2136+ %- ~(uni in ber)
2137+ ^- (set tako)
2138+ %+ roll p.yak
2139+ |= [yek=tako bar=(set tako)]
2140+ ^- (set tako)
2141+ ?: (~(has in bar) yek) :: save some time
2142+ bar
2143+ %- ~(uni in bar)
2144+ ^$(yak (tako-to-yaki yek))
2145+```
2146+
2147+We take a possible starting commit and a definite ending commit, and we
2148+produce the set of commits and the set of data between them.
2149+
2150+We let `sar` be the set of commits reachable from `a`. If `a` is null,
2151+then obviously no commits are reachable. Otherwise, we call
2152+`++reachable-takos` to calculate this.
2153+
2154+```hoon
2155+ ++ reachable-takos :: reachable
2156+ |= p=tako :: XX slow
2157+ ^- (set tako)
2158+ =+ y=(tako-to-yaki p)
2159+ =+ t=(~(put in _(set tako)) p)
2160+ %+ roll p.y
2161+ |= [q=tako s=_t]
2162+ ?: (~(has in s) q) :: already done
2163+ s :: hence skip
2164+ (~(uni in s) ^$(p q)) :: otherwise traverse
2165+```
2166+
2167+We very simply produce the set of the given tako plus its parents,
2168+recursively.
2169+
2170+Back in `++reachable-between-takos`, we let `yak` be the yaki of `b`,
2171+the ending commit. With this, we create a set that is the union of `sar`
2172+and all takos reachable from `b`.
2173+
2174+We pass `sar` into `++new-lobes` to get all the lobes referenced by any
2175+tako referenced by `a`. The result is passed into `++new-lobes-takos` to
2176+do the same, but not recomputing those in already calculated last
2177+sentence. This produces the sets of takos and lobes we need.
2178+
2179+```hoon
2180+ ++ new-lobes :: object hash set
2181+ |= [b=(set lobe) a=(set tako)] :: that aren't in b
2182+ ^- (set lobe)
2183+ %+ roll (~(tap in a) ~)
2184+ |= [tak=tako bar=(set lobe)]
2185+ ^- (set lobe)
2186+ =+ yak=(tako-to-yaki tak)
2187+ %+ roll (~(tap by q.yak) ~)
2188+ |= [[path lob=lobe] far=_bar]
2189+ ^- (set lobe)
2190+ ?~ (~(has in b) lob) :: don't need
2191+ far
2192+ =+ gar=(lobe-to-blob lob)
2193+ ?- -.gar
2194+ %direct (~(put in far) lob)
2195+ %delta (~(put in $(lob q.gar)) lob)
2196+ %indirect (~(put in $(lob s.gar)) lob)
2197+ ==
2198+```
2199+
2200+Here, we're creating a set of lobes referenced in a commit in `a`. We
2201+start out with `b` as the initial set of lobes, so we don't need to
2202+recompute any of the lobes referenced in there.
2203+
2204+The algorithm is pretty simple, so we won't bore you with the details.
2205+We simply traverse every commit in `a`, looking at every blob referenced
2206+there, and, if it's not already in `b`, we add it to `b`. In the case of
2207+a direct blob, we're done. For a delta or an indirect blob, we
2208+recursively add every blob referenced within the blob.
2209+
2210+```hoon
2211+ ++ new-lobes-takos :: garg & repack
2212+ |= [b=(set lobe) a=(set tako)]
2213+ ^- [(set tako) (set lobe)]
2214+ [a (new-lobes b a)]
2215+```
2216+
2217+Here, we just update the set of lobes we're given with the commits we're
2218+given and produce both sets.
2219+
2220+This concludes our discussion of a local subscription.
2221+
2222+## Lifecycle of a Foreign Read or Subscription
2223+
2224+Foreign reads and subscriptions are handled in much the same way as
2225+local ones. The interface is the same -- a vane or app sends a `%warp`
2226+kiss with the request. The difference is simply that the `sock` refers
2227+to the foreign ship.
2228+
2229+Thus, we start in the same place -- in `++call`, handling `%warp`.
2230+However, since the two side of the `sock` are different, we follow a
2231+different path.
2232+
2233+```hoon
2234+ =+ wex=(do now p.q.hic p.q.q.hic ruf)
2235+ =+ ^= woo
2236+ ?~ q.q.q.hic
2237+ abet:(ease:wex hen)
2238+ abet:(eave:wex hen u.q.q.q.hic)
2239+ [-.woo (posh q.p.q.hic p.q.q.hic +.woo ruf)]
2240+```
2241+
2242+If we compare this to how the local case was handled, we see that it's
2243+not all that different. We use `++do` rather than `++un` and `++de` to
2244+set up the core for the foreign ship. This gives us a `++de` core, so we
2245+either cancel or begin the request by calling `++ease` or `++eave`,
2246+exactly as in the local case. In either case, we call `++abet:de` to
2247+resolve our various types of output into actual moves, as described in
2248+the local case. Finally, we call `++posh` to update our raft, putting
2249+the modified rung into the raft.
2250+
2251+We'll first trace through `++do`.
2252+
2253+```hoon
2254+ ++ do
2255+ |= [now=@da [who=ship him=ship] syd=@tas ruf=raft]
2256+ =+ ^= rug ^- rung
2257+ =+ rug=(~(get by hoy.ruf) him)
2258+ ?^(rug u.rug *rung)
2259+ =+ ^= red ^- rede
2260+ =+ yit=(~(get by rus.rug) syd)
2261+ ?^(yit u.yit `rede`[~2000.1.1 ~ [~ *rind] *dome])
2262+ ((de now ~ ~) [who him] syd red ran.ruf)
2263+```
2264+
2265+If we already have a rung for this foreign ship, then we use that.
2266+Otherwise, we create a new blank one. If we already have a rede in this
2267+rung, then we use that, otherwise we create a blank one. An important
2268+point to note here is that we let `ref` in the rede be `[~ *rind]`.
2269+Recall, for domestic desks `ref` is null. We use this to distinguish
2270+between foreign and domestic desks in `++de`.
2271+
2272+With this information, we create a `++de` core as usual.
2273+
2274+Although we've already covered `++ease` and `++eave`, we'll go through
2275+them quickly again, highlighting the case of foreign request.
2276+
2277+```hoon
2278+ ++ ease :: release request
2279+ |= hen=duct
2280+ ^+ +>
2281+ ?~ ref +>
2282+ =+ rov=(~(got by qyx) hen)
2283+ =. qyx (~(del by qyx) hen)
2284+ (mabe rov (cury best hen))
2285+ =. qyx (~(del by qyx) hen)
2286+ |- ^+ +>+.$
2287+ =+ nux=(~(get by fod.u.ref) hen)
2288+ ?~ nux +>+.$
2289+ %= +>+.$
2290+ say [[hen [(scot %ud u.nux) ~] for [u.nux syd ~]] say]
2291+ fod.u.ref (~(del by fod.u.ref) hen)
2292+ bom.u.ref (~(del by bom.u.ref) u.nux)
2293+ ==
2294+```
2295+
2296+Here, we still remove the duct from our cult (we maintain a cult even
2297+for foreign desks), but we also need to tell the foreign desk to cancel
2298+our subscription. We do this by sending a request (by appending to
2299+`say`, which gets resolved in `++abet:de` to a `%want` kiss to ames) to
2300+the foreign ship to cancel the subscription. Since we don't anymore
2301+expect a response on this duct, we remove it from `fod` and `bom`, which
2302+are the maps between ducts, raves, and request sequence numbers.
2303+Basically, we remove every trace of the subscription from our request
2304+manager.
2305+
2306+In the case of `++eave`, where we're creating a new request, everything
2307+is exactly identical to the case of the local request except `++duce`.
2308+We said that `++duce` simply puts the request into our cult. This is
2309+true for a domestic request, but distinctly untrue for foreign requests.
2310+
2311+```hoon
2312+ ++ duce :: produce request
2313+ |= [hen=duct rov=rove]
2314+ ^+ +>
2315+ =. qyx (~(put by qyx) hen rov)
2316+ ?~ ref +>.$
2317+ |- ^+ +>+.$ :: XX why?
2318+ =+ rav=(reve rov)
2319+ =+ ^= vaw ^- rave
2320+ ?. ?=([%& %v *] rav) rav
2321+ [%| [%ud let.dom] `case`q.p.rav r.p.rav]
2322+ =+ inx=nix.u.ref
2323+ %= +>+.$
2324+ say [[hen [(scot %ud inx) ~] for [inx syd ~ vaw]] say]
2325+ nix.u.ref +(nix.u.ref)
2326+ bom.u.ref (~(put by bom.u.ref) inx [hen vaw])
2327+ fod.u.ref (~(put by fod.u.ref) hen inx)
2328+ ==
2329+```
2330+
2331+If we have a request manager (i.e. this is a foreign desk), then we do
2332+the approximate inverse of `++ease`. We create a rave out of the given
2333+request and send it off to the foreign desk by putting it in `say`. Note
2334+that the rave is created to request the information starting at the next
2335+revision number. Since this is a new request, we put it into `fod` and
2336+`bom` to associate the request with its duct and its sequence number.
2337+Since we're using another sequence number, we must increment `nix`,
2338+which represents the next available sequence number.
2339+
2340+And that's really it for this side of the request. Requesting foreign
2341+information isn't that hard. Let's see what it looks like on the other
2342+side. When we get a request from another ship for information on our
2343+ship, that comes to us in the form of a `%wart` from ames.
2344+
2345+We handle a `%wart` in `++call`, right next to where we handle the
2346+`%warp` case.
2347+
2348+```hoon
2349+ %wart
2350+ ?> ?=(%re q.q.hic)
2351+ =+ ryf=((hard riff) s.q.hic)
2352+ :_ ..^$
2353+ :~ :- hen
2354+ :^ %pass [(scot %p p.p.q.hic) (scot %p q.p.q.hic) r.q.hic]
2355+ %c
2356+ [%warp [p.p.q.hic p.p.q.hic] ryf]
2357+ ==
2358+```
2359+
2360+Every request we receive should be of type `riff`, so we coerce it into
2361+that type. We just convert this into a new `%warp` kiss that we pass to
2362+ourself. This gets handled like normal, as a local request. When the
2363+request produces a value, it does so like normal as a `%writ`, which is
2364+returned to `++take` along the path we just sent it on.
2365+
2366+```hoon
2367+ %writ
2368+ ?> ?=([@ @ *] tea)
2369+ =+ our=(need (slaw %p i.tea))
2370+ =+ him=(need (slaw %p i.t.tea))
2371+ :_ ..^$
2372+ :~ :- hen
2373+ [%pass ~ %a [%want [our him] [%r %re %c t.t.tea] p.+.q.hin]]
2374+ ==
2375+```
2376+
2377+Since we encoded the ship we need to respond to in the path, we can just
2378+pass our `%want` back to ames, so that we tell the requesting ship about
2379+the new data.
2380+
2381+This comes back to the original ship as a `%waft` from ames, which comes
2382+into `++take`, right next to where we handled `%writ`.
2383+
2384+```hoon
2385+ %waft
2386+ ?> ?=([@ @ ~] tea)
2387+ =+ syd=(need (slaw %tas i.tea))
2388+ =+ inx=(need (slaw %ud i.t.tea))
2389+ =+ ^= zat
2390+ =< wake
2391+ (knit:(do now p.+.q.hin syd ruf) [inx ((hard riot) q.+.q.hin)])
2392+ =^ mos ruf
2393+ =+ zot=abet.zat
2394+ [-.zot (posh q.p.+.q.hin syd +.zot ruf)]
2395+ [mos ..^$(ran.ruf ran.zat)] :: merge in new obj
2396+```
2397+
2398+This gets the desk and sequence number from the path the request was
2399+sent over. This determines exactly which request is being responded to.
2400+We call `++knit:de` to apply the changes to our local desk, and we call
2401+`++wake` to update our subscribers. Then we call `++abet:de` and
2402+`++posh` as normal (like in `++eave`).
2403+
2404+We'll examine `++knit` and `++wake`, in that order.
2405+
2406+```hoon
2407+ ++ knit :: external change
2408+ |= [inx=@ud rot=riot]
2409+ ^+ +>
2410+ ?> ?=(^ ref)
2411+ |- ^+ +>+.$
2412+ =+ ruv=(~(get by bom.u.ref) inx)
2413+ ?~ ruv +>+.$
2414+ => ?. |(?=(~ rot) ?=(& -.q.u.ruv)) .
2415+ %_ .
2416+ bom.u.ref (~(del by bom.u.ref) inx)
2417+ fod.u.ref (~(del by fod.u.ref) p.u.ruv)
2418+ ==
2419+ ?~ rot
2420+ =+ rav=`rave`q.u.ruv
2421+ %= +>+.$
2422+ lim
2423+ ?.(&(?=(| -.rav) ?=(%da -.q.p.rav)) lim `@da`p.q.p.rav)
2424+ ::
2425+ haw.u.ref
2426+ ?. ?=(& -.rav) haw.u.ref
2427+ (~(put by haw.u.ref) p.rav ~)
2428+ ==
2429+ ?< ?=(%v p.p.u.rot)
2430+ =. haw.u.ref
2431+ (~(put by haw.u.ref) [p.p.u.rot q.p.u.rot q.u.rot] ~ r.u.rot)
2432+ ?. ?=(%w p.p.u.rot) +>+.$
2433+ |- ^+ +>+.^$
2434+ =+ nez=[%w [%ud let.dom] ~]
2435+ =+ nex=(~(get by haw.u.ref) nez)
2436+ ?~ nex +>+.^$
2437+ ?~ u.nex +>+.^$ :: should never happen
2438+ =. +>+.^$ =+ roo=(edis ((hard nako) u.u.nex))
2439+ ?>(?=(^ ref.roo) roo)
2440+ %= $
2441+ haw.u.ref (~(del by haw.u.ref) nez)
2442+ ==
2443+```
2444+
2445+This is kind of a long gate, but don't worry, it's not bad at all.
2446+
2447+First, we assert that we're not a domestic desk. That wouldn't make any
2448+sense at all.
2449+
2450+Since we have the sequence number of the request, we can get the duct
2451+and rave from `bom` in our request manager. If we didn't actually
2452+request this data (or the request was canceled before we got it), then
2453+we do nothing.
2454+
2455+Else, we remove the request from `bom` and `fod` unless this was a
2456+subscription request and we didn't receive a null riot (which would
2457+indicate the last message on the subscription).
2458+
2459+Now, if we received a null riot, then if this was a subscription request
2460+by date, then we update `lim` in our request manager (representing the
2461+latest time at which we have complete information for this desk) to the
2462+date that was requested. If this was a single read request, then we put
2463+the result in our simple cache `haw` to make future requests faster.
2464+Then we're done.
2465+
2466+If we received actual data, then we put it into our cache `haw`. Unless
2467+it's a `%w` request, we're done.
2468+
2469+If it is a `%w` request, then we try to get the `%w` at our current head
2470+from the cache. In general, that should be the thing we just put in a
2471+moment ago, but that is not guaranteed. The most common case where this
2472+is different is when we receive desk updates out of order. At any rate,
2473+since we now have new information, we need to apply it to our local copy
2474+of the desk. We do so in `++edis`, and then we remove the stuff we just
2475+applied from the cache, since it's not really a true "single read", like
2476+what should really be in the cache.
2477+
2478+```hoon
2479+ ++ edis :: apply subscription
2480+ |= nak=nako
2481+ ^+ +>
2482+ %= +>
2483+ hit.dom (~(uni by hit.dom) gar.nak)
2484+ let.dom let.nak
2485+ lat.ran %+ roll (~(tap in bar.nak) ~)
2486+ =< .(yeb lat.ran)
2487+ |= [sar=blob yeb=(map lobe blob)]
2488+ =+ zax=(blob-to-lobe sar)
2489+ %+ ~(put by yeb) zax sar
2490+ hut.ran %+ roll (~(tap in lar.nak) ~)
2491+ =< .(yeb hut.ran)
2492+ |= [sar=yaki yeb=(map tako yaki)]
2493+ %+ ~(put by yeb) r.sar sar
2494+ ==
2495+```
2496+
2497+This shows, of course, exactly why nako is defined the way it is. To
2498+become completely up to date with the foreign desk, we need to merge
2499+`hit` with the foreign one so that we have all the revision numbers. We
2500+update `let` so that we know which revision is the head.
2501+
2502+We merge the new blobs in `lat`, keying them by their hash, which we get
2503+from a call to `++blob-to-lobe`. Recall that the hash is stored in the
2504+actual blob itself. We do the same thing to the new yakis, putting them
2505+in `hut`, keyed by their hash.
2506+
2507+Now, our local dome should be exactly the same as the foreign one.
2508+
2509+This concludes our discussion of `++knit`. Now the changes have been
2510+applied to our local copy of the desk, and we just need to update our
2511+subscribers. We do so in `++wake:de`.
2512+
2513+```hoon
2514+ ++ wake :: update subscribers
2515+ ^+ .
2516+ =+ xiq=(~(tap by qyx) ~)
2517+ =| xaq=(list ,[p=duct q=rove])
2518+ |- ^+ ..wake
2519+ ?~ xiq
2520+ ..wake(qyx (~(gas by *cult) xaq))
2521+ ?- -.q.i.xiq
2522+ &
2523+ =+ cas=?~(ref ~ (~(get by haw.u.ref) `mood`p.q.i.xiq))
2524+ ?^ cas
2525+ %= $
2526+ xiq t.xiq
2527+ ..wake ?~ u.cas (blub p.i.xiq)
2528+ (blab p.i.xiq p.q.i.xiq u.u.cas)
2529+ ==
2530+ =+ nao=(~(case-to-aeon ze lim dom ran) q.p.q.i.xiq)
2531+ ?~ nao $(xiq t.xiq, xaq [i.xiq xaq])
2532+ $(xiq t.xiq, ..wake (balk p.i.xiq u.nao p.q.i.xiq))
2533+ ::
2534+ |
2535+ =+ mot=`moot`p.q.i.xiq
2536+ =+ nab=(~(case-to-aeon ze lim dom ran) p.mot)
2537+ ?~ nab
2538+ $(xiq t.xiq, xaq [i.xiq xaq])
2539+ =+ huy=(~(case-to-aeon ze lim dom ran) q.mot)
2540+ ?~ huy
2541+ =+ ptr=[%ud +(let.dom)]
2542+ %= $
2543+ xiq t.xiq
2544+ xaq [[p.i.xiq [%| ptr q.mot r.mot s.mot]] xaq]
2545+ ..wake =+ ^= ear
2546+ (~(lobes-at-path ze lim dom ran) let.dom r.p.q.i.xiq)
2547+ ?: =(s.p.q.i.xiq ear) ..wake
2548+ =+ fud=(~(make-nako ze lim dom ran) u.nab let.dom)
2549+ (bleb p.i.xiq let.dom fud)
2550+ ==
2551+ %= $
2552+ xiq t.xiq
2553+ ..wake =- (blub:- p.i.xiq)
2554+ =+ ^= ear
2555+ (~(lobes-at-path ze lim dom ran) u.huy r.p.q.i.xiq)
2556+ ?: =(s.p.q.i.xiq ear) (blub p.i.xiq)
2557+ =+ fud=(~(make-nako ze lim dom ran) u.nab u.huy)
2558+ (bleb p.i.xiq +(u.nab) fud)
2559+ ==
2560+ ==
2561+ --
2562+```
2563+
2564+This is even longer than `++knit`, but it's pretty similar to `++eave`.
2565+We loop through each of our subscribers `xiq`, processing each in turn.
2566+When we're done, we just put the remaining subscribers back in our
2567+subscriber list.
2568+
2569+If the subscriber is a single read, then, if this is a foreign desk
2570+(note that `++wake` is called from other arms, and not only on foreign
2571+desks). Obviously, if we find an identical request there, then we can
2572+produce the result immediately. Referential transparency for the win. We
2573+produce the result with a call to `++blab`. If this is a foreign desk
2574+but the result is not in the cache, then we produce `++blub` (canceled
2575+subscription with no data) for reasons entirely opaque to me. Seriously,
2576+it seems like we should wait until we get an actual response to the
2577+request. If someone figures out why this is, let me know. At any rate,
2578+it seems to work.
2579+
2580+If this is a domestic desk, then we check to see if the case exists yet.
2581+If it doesn't, then we simply move on to the next subscriber, consing
2582+this one onto `xaq` so that we can check again the next time around. If
2583+it does exist, then we call `++balk` to fulfill the request and produce
2584+it.
2585+
2586+`++balk` is very simple, so we'll describe it here before we get to the
2587+subscription case.
2588+
2589+```hoon
2590+ ++ balk :: read and send
2591+ |= [hen=duct oan=@ud mun=mood]
2592+ ^+ +>
2593+ =+ vid=(~(read-at-aeon ze lim dom ran) oan mun)
2594+ ?~ vid (blub hen) (blab hen mun u.vid)
2595+```
2596+
2597+We call `++read-at-aeon` on the given request and aeon. If you recall,
2598+this processes a `mood` at a particular aeon and produces the result, if
2599+there is one. If there is data at the requested location, then we
2600+produce it with `++blab`. Else, we call `++blub` to notify the
2601+subscriber that no data can ever come over this subscriptioin since it
2602+is now impossible for there to ever be data for the given request.
2603+Because referential transparency.
2604+
2605+At any rate, back to `++wake`. If the given rave is a subscription
2606+request, then we proceed similarly to how we do in `++eave`. We first
2607+try to get the aeon referred to by the starting case. If it doesn't
2608+exist yet, then we can't do anything interesting with this subscription,
2609+so we move on to the next one.
2610+
2611+Otherwise, we try to get the aeon referred to by the ending case. If it
2612+doesn't exist yet, then we produce all the information we can. We call
2613+`++lobes-at-path` at the given aeon and path to see if the requested
2614+path has actually changed. If it hasn't, then we don't produce anything;
2615+else, we produce the correct nako by calling `++bleb` on the result of
2616+`++make-nako`, as in `++eave`. At any rate, we move on to the next
2617+subscription, putting back into our cult the current subscription with a
2618+new start case of the next aeon after the present.
2619+
2620+If the aeon referred to by the ending case does exist, then we drop this
2621+subscriber from our cult and satisfy its request immediately. This is
2622+the same as before -- we check to see if the data at the path has
2623+actually changed, producing it if it has; else, we call `++blub` since
2624+no more data can be produced over this subscription.
2625+
2626+This concludes our discussion of foreign requests.