code wiki / _hdl_build / nx_web_ingest.nx

nx_web_ingest.nx source

↩ module page · 235 lines · 11769 B

1// nx_web_ingest.nx -- OPEN-WEB front of nishi search: BFS-crawl the REAL web (sovereign TLS-1.3 + Mozilla CA, 2// polite, simhash near-dup killed) and ingest each kept page STRAIGHT into the shared "web" seg_store shard 3// (dp-web-pub-): doc:<cid> = the page's extracted text, url:<cid> = its ABSOLUTE url -> the /search?scope=web 4// SERP links results to the real pages. Composes the PROVEN pieces only: nx_crawl_web's fetch/link spine + 5// nx_corpus_ingest's writer/key/hash mechanics (ci_hash / ci_mkurlkey / fresh-segid batching, gate 7/7). 6// usage: nx_web_ingest <seed-url> <max_pages> 7// Bounded by max_pages AND the known per-process certloop budget (~19 fetches) -- crawl-at-scale = many small 8// runs, each committing its own segments (append-only, idempotent by content cid). license_tier: ORIGINAL 9import "nx_corpus_ingest.nx" // ci_hash / ci_mkurlkey / dss_prefix / dss_mkkey / seg_store (transitively) 10import "nx_x509_trust_store.nx" 11import "nx_trust_store_load_from_certdata.nx" 12import "nx_https_fetch_follow.nx" 13import "nx_simhash.nx" 14const K_MAGIC_8192: i64 = 8192 15const K_MAGIC_4194304: i64 = 4194304 16const K_MAGIC_8388608: i64 = 8388608 17const K_MAGIC_1048576: i64 = 1048576 18const K_MAGIC_2048: i64 = 2048 19 20func wi_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 21func wi_num(v: i64) -> i64 { 22 let bb: *u8 = sys_mmap(28); var m: i64 = v 23 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 24 let t: *u8 = sys_mmap(28); var k: i64 = 0 25 if m == 0 { t[0] = 48 as u8; k = 1 } 26 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 27 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 28 sys_write(1, bb, k); return 0 29} 30func wi_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 31func wi_atoi(s: *u8) -> i64 { var v: i64 = 0; var i: i64 = 0; while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } return v } 32 33// scheme://host base from the seed (relative-link resolution) -- mirrors nx_crawl_web.cw_base 34func wi_base(url: *u8, out: *u8) -> i64 { 35 let n: i64 = wi_len(url) 36 var schemeend: i64 = 0 37 var i: i64 = 0 38 var hit: i64 = 0 39 while hit == 0 { 40 if i + 2 >= n { hit = 1 } else { 41 if url[i] == (58 as u8) { if url[i+1] == (47 as u8) { if url[i+2] == (47 as u8) { schemeend = i + 3; hit = 1 } } } 42 if hit == 0 { i = i + 1 } 43 } 44 } 45 var e: i64 = schemeend 46 var go: i64 = 1 47 while go == 1 { if e >= n { go = 0 } else { if url[e] == (47 as u8) { go = 0 } else { e = e + 1 } } } 48 var k: i64 = 0 49 while k < e { out[k] = url[k]; k = k + 1 } 50 out[e] = 0 as u8 51 return e 52} 53func wi_eqn(a: *u8, alen: i64, b: *u8) -> i64 { 54 var i: i64 = 0; while i < alen { if a[i] != b[i] { return 0 } i = i + 1 } 55 if b[alen] != (0 as u8) { return 0 } 56 return 1 57} 58func wi_enqueue(url: *u8, ulen: i64, seen: **u8, nseen: *i64, queue: **u8, qt: *i64, cap: i64) -> i64 { 59 var s: i64 = 0; while s < nseen[0] { if wi_eqn(url, ulen, seen[s]) == 1 { return 0 } s = s + 1 } 60 if nseen[0] >= cap { return 0 } 61 let nu: *u8 = sys_mmap(ulen + 1); var i: i64 = 0; while i < ulen { nu[i] = url[i]; i = i + 1 } nu[ulen] = 0 as u8 62 seen[nseen[0]] = nu; queue[qt[0]] = nu; nseen[0] = nseen[0] + 1; qt[0] = qt[0] + 1 63 return 1 64} 65func wi_pre(h: *u8, hlen: i64, off: i64, lit: *u8, litlen: i64) -> i64 { 66 if off + litlen > hlen { return 0 } 67 var k: i64 = 0; while k < litlen { if h[off+k] != lit[k] { return 0 } k = k + 1 } return 1 68} 69func wi_lc(c: i64) -> i64 { if c >= 0x41 { if c <= 0x5a { return c + 0x20 } } return c } 70func wi_href_at(h: *u8, hlen: i64, off: i64) -> i64 { 71 if off + 5 > hlen { return 0 } 72 if wi_lc(h[off] as i64) != 0x68 { return 0 } 73 if wi_lc(h[off+1] as i64) != 0x72 { return 0 } 74 if wi_lc(h[off+2] as i64) != 0x65 { return 0 } 75 if wi_lc(h[off+3] as i64) != 0x66 { return 0 } 76 if (h[off+4] as i64) != 0x3d { return 0 } 77 return 1 78} 79// extract + resolve + enqueue outbound links (absolute http(s) + root-relative) 80func wi_links(h: *u8, hlen: i64, base: *u8, blen: i64, seen: **u8, nseen: *i64, queue: **u8, qt: *i64, cap: i64) -> i64 { 81 var found: i64 = 0 82 let scratch: *u8 = sys_mmap(K_MAGIC_8192) 83 var i: i64 = 0 84 while i < hlen { 85 var step: i64 = 1 86 if wi_href_at(h, hlen, i) == 1 { 87 let q: i64 = h[i+5] as i64 88 var quoted: i64 = 0 89 if q == 0x22 { quoted = 1 } 90 if q == 0x27 { quoted = 1 } 91 if quoted == 1 { 92 let cs: i64 = i + 6 93 var e: i64 = cs 94 var run: i64 = 1 95 while run == 1 { run = 0; if e < hlen { if (h[e] as i64) != q { e = e + 1; run = 1 } } } 96 let clen: i64 = e - cs 97 if clen > 0 { 98 if wi_pre(h, hlen, cs, "https://" as *u8, 8) == 1 { 99 if wi_enqueue(((h as i64)+cs) as *u8, clen, seen, nseen, queue, qt, cap) == 1 { found = found + 1 } 100 } else { if wi_pre(h, hlen, cs, "http://" as *u8, 7) == 1 { 101 if wi_enqueue(((h as i64)+cs) as *u8, clen, seen, nseen, queue, qt, cap) == 1 { found = found + 1 } 102 } else { 103 if (h[cs] as i64) == 0x2f { 104 var protorel: i64 = 0 105 if clen >= 2 { if (h[cs+1] as i64) == 0x2f { protorel = 1 } } 106 if protorel == 0 { if blen + clen + 1 < K_MAGIC_8192 { 107 var b: i64 = 0; while b < blen { scratch[b] = base[b]; b = b + 1 } 108 var c: i64 = 0; while c < clen { scratch[blen+c] = h[cs+c]; c = c + 1 } 109 scratch[blen+clen] = 0 as u8 110 if wi_enqueue(scratch, blen + clen, seen, nseen, queue, qt, cap) == 1 { found = found + 1 } 111 } } 112 } 113 } } 114 } 115 step = (e - i) + 1 116 } 117 } 118 i = i + step 119 } 120 return found 121} 122 123func main(argc: i64, argv: *i64) -> i64 { 124 if argc < 3 { wi_puts("usage: nx_web_ingest <seed-url> <max_pages>\n" as *u8); return 1 } 125 let seed: *u8 = argv[1] as *u8 126 let max_pages: i64 = wi_atoi(argv[2] as *u8) 127 let r: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 512, K_MAGIC_4194304) 128 if r <= 0 { wi_puts("certdata load failed\n" as *u8); return 2 } 129 let store: *TrustStore = r as *TrustStore 130 wi_puts("=== nx_web_ingest: crawl -> dp-web-pub- (sovereign open-web search corpus) ===\n" as *u8) 131 132 let prefix: *u8 = sys_mmap(512) 133 dss_prefix("web" as *u8, prefix) 134 // fresh segid past the manifest max (append-only, never clobber) 135 let segs: *i64 = sys_mmap(256 * 8) as *i64 136 let nseg: i64 = ss_manifest_file(prefix, "manifest.txt" as *u8, segs) 137 var segid: i64 = 1 138 var si: i64 = 0 139 // ROOT FIX seq1730 (id 1785450987): segs[] holds POINTERS to seg-<id> name strings 140 // (nx_seg_store.nx:1234 stores segs[cnt] = name as i64), NOT ids -- so segs[si] + 1 produced 141 // MMAP_ADDRESS+1 (~1.4e14), the pointer-shaped poison that PINS a plane forever: every later 142 // epoch id sorts BELOW it in supersede order and its rows are silently shadowed while rc=0. 143 // Parse the DIGITS, as nx_web_shard_compact.nx:55-58 already does on this SAME array. 144 while si < nseg { 145 let sg_nm: *u8 = segs[si] as *u8 146 var sg_v: i64 = 0 147 var sg_ci: i64 = 0 148 while sg_nm[sg_ci] != (0 as u8) { let sg_c: i64 = sg_nm[sg_ci] as i64; if sg_c >= 48 { if sg_c <= 57 { sg_v = sg_v * 10 + (sg_c - 48) } } sg_ci = sg_ci + 1 } 149 if sg_v >= segid { segid = sg_v + 1 } 150 si = si + 1 151 } 152 let h: *i64 = ss_open(prefix) 153 let pbox: *i64 = sys_mmap(16) as *i64 154 let lbox: *i64 = sys_mmap(16) as *i64 155 156 let cap: i64 = K_MAGIC_8388608 157 let out: *u8 = sys_mmap(cap) 158 let tcap: i64 = K_MAGIC_1048576 159 let text: *u8 = sys_mmap(tcap) 160 let status: *i64 = sys_mmap(8) as *i64 161 let QCAP: i64 = 512 162 let queue: **u8 = sys_mmap(QCAP * 8) as **u8 163 let seen: **u8 = sys_mmap(QCAP * 8) as **u8 164 let qt: *i64 = sys_mmap(8) as *i64; qt[0] = 0 165 let nseen: *i64 = sys_mmap(8) as *i64; nseen[0] = 0 166 var qh: i64 = 0 167 let keptfp: *i64 = sys_mmap(128 * 8) as *i64 168 let base: *u8 = sys_mmap(K_MAGIC_2048) 169 let blen: i64 = wi_base(seed, base) 170 wi_enqueue(seed, wi_len(seed), seen, nseen, queue, qt, QCAP) 171 172 let key: *u8 = sys_mmap(64) 173 let ukey: *u8 = sys_mmap(64) 174 var w: *i64 = ss_begin() 175 var crawled: i64 = 0 176 var ingested: i64 = 0 177 var present: i64 = 0 178 var segments: i64 = 0 179 var running: i64 = 1 180 while running == 1 { 181 if qh >= qt[0] { running = 0 } 182 if crawled >= max_pages { running = 0 } 183 if running == 1 { 184 let url: *u8 = queue[qh]; qh = qh + 1 185 sys_sleep_ms(350) 186 let n: i64 = nx_https_fetch_follow(url, store, out, cap, 6, status) 187 if n > 0 { if status[0] == 200 { 188 let tlen: i64 = nx_html_to_text(out, n, text, tcap) 189 if tlen >= CI_MINDOC { 190 let fp: i64 = nx_simhash_fingerprint(text, tlen) 191 var dup: i64 = 0 192 var k: i64 = 0 193 while k < crawled { if nx_simhash_hamming(fp, keptfp[k]) <= 4 { dup = 1 } k = k + 1 } 194 if dup == 0 { 195 if crawled < 128 { keptfp[crawled] = fp } 196 crawled = crawled + 1 197 var tn: i64 = tlen 198 if tn > CI_DOCCAP { tn = CI_DOCCAP } 199 let cid: i64 = ci_hash(text, tn) 200 dss_mkkey(cid, key) 201 var already: i64 = 0 202 if (h as i64) != 0 { if ss_hget(h, key, pbox, lbox) == 1 { already = 1 } } 203 if already == 1 { present = present + 1 } else { 204 if ss_add(w, 1, key, text, tn) < 0 { 205 if ss_commit(prefix, w, segid) == 0 { segments = segments + 1 } 206 segid = segid + 1 207 w = ss_begin() 208 ss_add(w, 1, key, text, tn) 209 } 210 ci_mkurlkey(cid, ukey) 211 if ss_add(w, 1, ukey, url, wi_len(url)) < 0 { 212 if ss_commit(prefix, w, segid) == 0 { segments = segments + 1 } 213 segid = segid + 1 214 w = ss_begin() 215 ss_add(w, 1, ukey, url, wi_len(url)) 216 } 217 ingested = ingested + 1 218 wi_puts(" ingested #" as *u8); wi_num(ingested); wi_puts(" " as *u8); wi_puts(url); wi_puts(" (" as *u8); wi_num(tn); wi_puts(" chars)\n" as *u8) 219 } 220 wi_links(out, n, base, blen, seen, nseen, queue, qt, QCAP) 221 } 222 } 223 } } 224 } 225 } 226 if w[1] > 0 { if ss_commit(prefix, w, segid) == 0 { segments = segments + 1 } } 227 wi_puts("WEB-INGEST done: crawled=" as *u8); wi_num(crawled) 228 wi_puts(" ingested=" as *u8); wi_num(ingested) 229 wi_puts(" already_present=" as *u8); wi_num(present) 230 wi_puts(" segments=" as *u8); wi_num(segments) 231 wi_puts(" -> dp-web-pub-\n" as *u8) 232 if ingested + present >= 1 { wi_puts("WEB-INGEST GREEN\n" as *u8); return 0 } 233 wi_puts("WEB-INGEST RED (nothing ingested)\n" as *u8) 234 return 3 235}