code wiki / (root) / nx_mvault_layout.nx

nx_mvault_layout.nx source

↩ module page · 65 lines · 2794 B

1// nx_mvault_layout.nx -- DSM-native on-disk layout for vault blobs. 2// 3// GOAL (operator 2026-07-17): "structured on disk ... so it works with the 4// synology dsm os but still has all of our capabilities so i dont have a 5// million folders and files." 6// 7// LAYOUT: <root>/<class>/<type>/<shard>/<cid16>_<source>.<ext> 8// class = gen | real (the two major sections) 9// type = image|gif|video|audio|story|page|manga|model3d|audiobook 10// shard = 2 hex chars of the CID (<=256 dirs per type) 11// file = <cid16>_<source>.<ext> (real ext => DSM Photos/Video 12// index it; CID + source VISIBLE in File Station) 13// 14// FAN-OUT BOUND: classes(2) x types(<=10) x shards(256) = <=5120 leaf dirs, 15// NEVER per-item folders. Metadata does NOT live in per-item sidecars -- it 16// lives in the seg-store (nx_mvault_record), a few segment files. So on-disk 17// file count ~= media count, folder count ~= 5120. No million-folders trap. 18// 19// SELF-DESCRIBING: class/type/source/cid are all recoverable from the path 20// alone, so DSM-side browsing works even without the seg-store; the seg-store 21// is the rich classified+searchable index over the same blobs (ref = path). 22// 23// Composes nx_mvault_ingest (mv_class_str / mv_type_str). license_tier: ORIGINAL 24 25import "nx_syscalls.nx" 26import "nx_mvault_ingest.nx" 27 28func dp_cat(dst: *u8, off: i64, s: *u8) -> i64 { 29 var i: i64 = 0 30 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 31 return off + i 32} 33 34func dp_ch(dst: *u8, off: i64, ch: i64) -> i64 { 35 dst[off] = ch as u8 36 return off + 1 37} 38 39// Build the DSM on-disk path for an item into `out` (NUL-terminated); ret len. 40// cid is the "nxc1-<64hex>" string; shard + stem come from its hex prefix. 41func mv_disk_path(out: *u8, root: *u8, class_code: i64, type_code: i64, 42 cid: *u8, source: *u8, ext: *u8) -> i64 { 43 let cs: *u8 = mv_class_str(class_code) 44 let ts: *u8 = mv_type_str(type_code) 45 var o: i64 = 0 46 o = dp_cat(out, o, root) // /volume1/vault 47 o = dp_ch(out, o, 47) // / 48 o = dp_cat(out, o, cs) // gen | real 49 o = dp_ch(out, o, 47) 50 o = dp_cat(out, o, ts) // image | video | ... 51 o = dp_ch(out, o, 47) 52 // shard = first 2 hex chars after the "nxc1-" prefix (cid[5], cid[6]) 53 out[o] = cid[5]; o = o + 1 54 out[o] = cid[6]; o = o + 1 55 o = dp_ch(out, o, 47) 56 // filename stem = 16 hex chars of the CID hash (unique enough; short) 57 var k: i64 = 0 58 while k < 16 { out[o] = cid[5 + k]; o = o + 1; k = k + 1 } 59 o = dp_ch(out, o, 95) // _ 60 o = dp_cat(out, o, source) // tumblr 61 o = dp_ch(out, o, 46) // . 62 o = dp_cat(out, o, ext) // mp4 63 out[o] = 0 as u8 64 return o 65}