tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

indexed-write.tri (1991B)


      1 !import io_v2 as IO
      2 !import base as B
      3 !export hash
      4 !export write
      5 !export publish
      6 !export roundTrip
      7 
      8 hash limit tree = IO.io (IO.hashIndexedTree limit tree)
      9 
     10 -- In-place transport, deliberately not atomic replacement. Failed preflight does
     11 -- not touch this already-open writer; opening an absent update file creates it.
     12 write path limit digest tree = IO.io <| IO.scope (owner : do IO.onOk
     13   writer <- IO.openUpdate owner path
     14   IO.writeIndexedTree writer limit digest tree)
     15 
     16 -- Source owns naming/publication and exact winner verification. "exists" means
     17 -- byte-verified at observation time, not crash durability or future immutability.
     18 publish directory limit tree = IO.io <| IO.scope (owner : do IO.onOk
     19   info <- IO.hashIndexedTree limit tree
     20   case info of
     21     [size digest] = do IO.onOk
     22       stage <- IO.openStage owner directory
     23       IO.writeIndexedTree stage limit digest tree
     24       IO.sealStage stage
     25       state <- IO.publishNew stage (B.append directory (B.append "/" digest))
     26       case state of
     27         "published" = IO.pure (B.ok [state size digest] t)
     28         "exists" = do IO.onOk
     29           reader <- IO.openReader owner (B.append directory (B.append "/" digest))
     30           IO.verifyIndexedTree reader limit tree
     31           end <- IO.readSome reader 1
     32           case end of
     33             ("eof", t) = IO.pure (B.ok [state size digest] t)
     34             _ = IO.pure (B.err ["invalid-data" "indexed-file/verify" "trailing bytes" "unknown"] t)
     35         _ = IO.fail "Invalid publication reply"
     36     _ = IO.fail "Invalid indexed hash reply")
     37 
     38 -- A shared DAG enters and leaves without ever becoming an expanded source byte
     39 -- list. This fixture expects canonical input; the writer checks its digest again.
     40 roundTrip input output directory limit size digest = IO.io <| IO.scope (owner : do IO.onOk
     41   reader <- IO.openReader owner input
     42   tree <- IO.readIndexedTree reader directory limit size digest
     43   writer <- IO.openWriter owner output
     44   IO.writeIndexedTree writer limit digest tree)