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