CUBELinux-2: WordFlags/tri-channel 16-bit flag field, tag-14 + scan_by_word_flag, cubetrace capture→replay→golden→lineage, CUBE VP-tree balling index (cubecode::ballindex), cubefs-visible WordFlags, and cube-mvw (sharded multi-writer MVCC store with per-shard WALs + group-commit + compaction, impl CubeBackend => CubeStore<MvwBackend> DB). Adds show-flags/scan-word-flags/trace-*/golden-capture CLI; ~ tests green.
This commit is contained in:
@@ -169,6 +169,7 @@ mod record_codec {
|
||||
// 9 total_remote_accesses (u64 le)
|
||||
// 10 last_access (u64 le)
|
||||
// 11 last_remote_access (u64 le)
|
||||
// 14 word_flags (u16 le) — per-word 16-bit tri-channel WordFlags
|
||||
// 13 path (utf8) — POSIX path metatag (the original filesystem path a
|
||||
// record was migrated from). Carries the directory hierarchy as DATA
|
||||
// so the associative query layer can reconstruct nesting from flags.
|
||||
@@ -226,6 +227,11 @@ mod record_codec {
|
||||
out.push(12);
|
||||
out.extend_from_slice(&h.flags.bits().to_le_bytes());
|
||||
}
|
||||
// Tag 14: per-word 16-bit tri-channel WordFlags field (see cubecoords).
|
||||
if h.word_flags.bits() != 0 {
|
||||
out.push(14);
|
||||
out.extend_from_slice(&h.word_flags.bits().to_le_bytes());
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
@@ -316,6 +322,14 @@ mod record_codec {
|
||||
h.flags = cubecoords::HeaderFlags::flags_from_bits(raw);
|
||||
b = &b[2..];
|
||||
}
|
||||
14 => {
|
||||
if b.len() < 2 {
|
||||
return None;
|
||||
}
|
||||
let raw = u16::from_le_bytes([b[0], b[1]]);
|
||||
h.word_flags = cubecoords::WordFlags::from_bits(raw);
|
||||
b = &b[2..];
|
||||
}
|
||||
_ => return None, // unknown tag -> reject (strict at Package 1)
|
||||
}
|
||||
}
|
||||
@@ -543,6 +557,25 @@ impl<B: CubeBackend> CubeStore<B> {
|
||||
out
|
||||
}
|
||||
|
||||
/// Query records by per-word flag (the 16-bit WordFlags metadata stripe
|
||||
/// carried in the header, tag 14). Parallel to [`scan_by_flag`] but on
|
||||
/// `word_flags`, so per-word metadata (encrypted/compressed/stego/type/
|
||||
/// arrangement/continuation) is queryable without decoding the body.
|
||||
pub fn scan_by_word_flag(&self, flag: u16) -> Vec<Czyx> {
|
||||
let mut out: Vec<Czyx> = self
|
||||
.backend
|
||||
.keys()
|
||||
.into_iter()
|
||||
.filter(|k| {
|
||||
self.get_record(k)
|
||||
.map(|(h, _)| h.word_flags.has(flag))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.collect();
|
||||
out.sort();
|
||||
out
|
||||
}
|
||||
|
||||
/// PDF Package 2 API: `scan_by_type` — query records by `doc_type`
|
||||
/// (the "event type" / file-extension analogue the PDF calls Flag 2).
|
||||
///
|
||||
@@ -683,6 +716,25 @@ mod tests {
|
||||
assert!(rh.flags.has(cubecoords::HeaderFlags::HAS_ASSOCIATIONS));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn word_flags_roundtrip() {
|
||||
let mut h = CubeHeader::new();
|
||||
h.word_flags = cubecoords::WordFlags::from_bits(
|
||||
cubecoords::WordFlags::ENCRYPTED
|
||||
| cubecoords::WordFlags::CONTINUATION
|
||||
| (cubecoords::WordFlags::TYPE_MASK & 0b11),
|
||||
);
|
||||
let enc = super::record_codec::encode_header(&h);
|
||||
let dec = super::record_codec::decode_header(&enc).unwrap();
|
||||
assert_eq!(dec.word_flags.bits(), h.word_flags.bits(), "word_flags must round-trip");
|
||||
// refresh_flags recomputes only the per-RECORD HeaderFlags; the separate
|
||||
// per-word word_flags field must be preserved untouched.
|
||||
let mut dec2 = dec;
|
||||
dec2.refresh_flags();
|
||||
assert_eq!(dec2.word_flags.bits(), h.word_flags.bits());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_record_is_none() {
|
||||
let store = CubeStore::new(HashBackend::new());
|
||||
@@ -779,6 +831,23 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scan_by_word_flag_finds_records() {
|
||||
let mut store = CubeStore::new(HashBackend::new());
|
||||
let mut h = CubeHeader::new();
|
||||
h.word_flags = cubecoords::WordFlags::from_bits(cubecoords::WordFlags::ENCRYPTED);
|
||||
store.put_record(Czyx::new(200, 5, 1, 1), &h, b"secret body");
|
||||
|
||||
let mut h2 = CubeHeader::new();
|
||||
h2.doc_type = Some("plain".into());
|
||||
h2.refresh_flags();
|
||||
store.put_record(Czyx::new(200, 5, 2, 2), &h2, b"plain body");
|
||||
|
||||
let enc = store.scan_by_word_flag(cubecoords::WordFlags::ENCRYPTED);
|
||||
assert_eq!(enc, vec![Czyx::new(200, 5, 1, 1)]);
|
||||
assert!(!enc.contains(&Czyx::new(200, 5, 2, 2)));
|
||||
}
|
||||
|
||||
/// `scan_by_type` is the concrete "log lookup by query" — pull every record
|
||||
/// of a given event type without knowing its coordinate.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user