code wiki / _hdl_build / nx_coedit.nx
nx_coedit.nx
buildroot/runtime/_hdl_build/nx_coedit.nx
about
nx_coedit.nx -- COLLABORATIVE-EDITING KERNEL (office census OF-C1's engine half): an RGA text CRDT.
Multiple replicas edit the SAME document concurrently; their op logs MERGE deterministically -- the same
final text on every replica REGARDLESS of merge order (convergence), no lost updates, tombstoned deletes,
deterministic (counter,replica) tie-break for concurrent inserts at the same point.
OP LOG (append-only, LF lines; the natural fit for the additive-only store doctrine):
I <replica> <counter> <afterid> <char> insert ONE byte after node <afterid> ("R" = document root)
D <replica> <counter> <targetid> tombstone node <targetid>
ids are "<replica>:<counter>"; an op's id must be UNIQUE (same id + different content = LOUD protocol
violation; identical duplicate = idempotent skip, which is what makes re-merging safe).
<char> is one byte, escaped: \n=newline \t=tab \s=space \\=backslash (any other 1 byte literal).
COMMANDS
apply <log> <out.txt> materialize (RGA linearization) -> file + verdict line
ins <log> <rep> <ctr> <afterid> <char> append a raw insert op
del <log> <rep> <ctr> <targetid> append a raw delete op
merge <A> <B> <out> union by op id (idempotent dedup; conflicting id = LOUD)
edit <log> <rep> <pos> ins <text> position-based convenience: per-BYTE ops chained after the
edit <log> <rep> <pos> del <count> visible byte at pos-1 / tombstones for [pos,pos+count)
HONEST SCOPE (v1, named): the KERNEL -- byte-granular ops (UTF-8 sequences survive as consecutive ops but
byte-position edits must not split a sequence), logs are plain files, ops cap 65536/doc. LIVE multi-client
sync (the R2 daemon + browser surface) is NOT built yet; the census OF-C1 axis stays ABSENT until R2 --
its needle requires the R2 sync function DEFINITION, which this file intentionally does not contain.
license_tier: ORIGINAL
dependencies 1 imports · 0 importers
imports: nx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 81 | struct CdDoc |
consts
| 27 | const CD_MAGIC_1000003: i64 = 1000003 |
| 28 | const CD_MAGIC_10007: i64 = 10007 |
| 29 | const CD_MAGIC_12289: i64 = 12289 |
| 30 | const CD_MAGIC_4194320: i64 = 4194320 |
| 31 | const CD_MAGIC_4194304: i64 = 4194304 |
| 32 | const CD_MAGIC_4294967296: i64 = 4294967296 |
| 33 | const CD_MAGIC_8388640: i64 = 8388640 |
| 34 | const CD_MAGIC_8388608: i64 = 8388608 |
| 35 | const CD_MAGIC_8388600: i64 = 8388600 |
| 37 | const CD_MAXOPS: i64 = 65536 |
| 38 | const CD_HASHN: i64 = 262144 // open-addressing id -> node-idx+1 (power of two) |
functions
| 40 | func cd_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8) { n=n+1 } return n } |
| 41 | func cd_puts(s: *u8) -> i64 { sys_write(1, s, cd_slen(s)); return 0 } |
| 42 | func cd_num(v: i64) -> i64 |
| 48 | func cd_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8) { if a[i]!=b[i] { return 0 } i=i+1 } if b[i]!=(0 as u8) { return 0 } return 1 } called by 1: main |
| 49 | func cd_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8) { dst[off+i]=s[i]; i=i+1 } return off+i } |
| 50 | func cd_uint(dst: *u8, off: i64, v: i64) -> i64 |
| 55 | func cd_readfile(path: *u8, buf: *u8, cap: i64) -> i64 called by 5: cd_loadfilecd_maxctrcd_sync_appendcd_live_syncmain calls 3: sys_openat_rdsys_readsys_close |
| 60 | func cd_appendfile(path: *u8, line: *u8, n: i64) -> i64 |
| 64 | func cd_writefile(path: *u8, buf: *u8, n: i64) -> i64 |
| 70 | func cd_int(s: *u8, ip: *i64, e: i64) -> i64 |
| 93 | func cd_new() -> *CdDoc |
| 107 | func cd_hkey(rep: i64, ctr: i64) -> i64 |
| 113 | func cd_hfind(d: *CdDoc, rep: i64, ctr: i64) -> i64 { // node idx or -1 |
| 127 | func cd_hput(d: *CdDoc, rep: i64, ctr: i64, ix: i64) -> i64 |
| 139 | func cd_newer(ra: i64, ca: i64, rb: i64, cb: i64) -> i64 called by 1: cd_link |
| 147 | func cd_link(d: *CdDoc, pidx: i64, ix: i64) -> i64 |
| 171 | func cd_unesc(s: *u8, i: i64, e: i64, out: *u8) -> i64 called by 1: cd_load |
| 189 | func cd_idtok(s: *u8, ip: *i64, e: i64, rc: *i64) -> i64 |
| 212 | func cd_load(d: *CdDoc, log: *u8, ln: i64) -> i64 |
| 310 | func cd_linear(d: *CdDoc, out: *u8, vis: *i64) -> i64 |
| 340 | func cd_loadfile(d: *CdDoc, path: *u8) -> i64 |
| 348 | func cd_escput(dst: *u8, off: i64, b: i64) -> i64 |
| 359 | func cd_maxctr(path: *u8, rep: i64) -> i64 |
| 383 | func cd_fail(msg: *u8, code: i64) -> i64 |
| 400 | func cd_seen_mark(seen: *i64, rep: i64, ctr: i64, isdel: i64) -> i64 { // returns 1 if NEW, 0 if already present |
| 415 | func cd_scan_dedup(buf: *u8, blen: i64, seen: *i64, out: *u8, emit: i64) -> i64 |
| 445 | func cd_sync_append(logpath: *u8, body: *u8, blen: i64) -> i64 called by 1: cd_live_sync calls 6: sys_mmapcd_readfilecd_scan_dedupsys_openat_appendsys_writesys_close |
| 465 | func cd_live_sync(logpath: *u8, is_post: i64, body: *u8, blen: i64, out: *u8, outcap: i64) -> i64 |
| 480 | func cd_hdrend(req: *u8, rn: i64) -> i64 |
| 486 | func cd_contentlen(req: *u8, he: i64) -> i64 |
| 508 | func cd_parsereq(req: *u8, rn: i64, bp: *i64) -> i64 |
| 516 | func cd_addr(out: *u8, port: i64) -> i64 called by 1: cd_serve |
| 524 | func cd_serve(logpath: *u8, port: i64, maxconns: i64) -> i64 |
| 581 | func rv_write_all_fd(fd: i64, buf: *u8, n: i64) -> i64 |
| 591 | func main(argc: i64, argv: *i64) -> i64 |