use regolith::{Db, IngestOptions, Options, SstFileWriter};
use tempfile::TempDir;
fn build(path: &std::path::Path, batch: usize, opts: &Options) {
let mut w = SstFileWriter::create(path, opts).unwrap();
for i in 0..64 {
w.put(
format!("ing_{batch:04}_{i:03}").as_bytes(),
format!("v{batch}").as_bytes(),
)
.unwrap();
}
w.finish().unwrap();
}
#[test]
fn no_writers_at_all() {
let dir = TempDir::new().unwrap();
let staging = TempDir::new().unwrap();
let opts = Options {
write_buffer_size: 32 * 1024,
..Options::default()
};
let db = Db::open(dir.path(), opts.clone()).unwrap();
for batch in 0..5usize {
let path = staging.path().join(format!("ing_{batch}.sst"));
build(&path, batch, &opts);
db.ingest_external_files(
std::slice::from_ref(&path),
IngestOptions {
snapshot_consistency: false,
..IngestOptions::default()
},
)
.unwrap();
let missing: Vec<usize> = (0..64)
.filter(|i| {
db.get(format!("ing_{batch:04}_{i:03}").as_bytes())
.unwrap()
.is_none()
})
.collect();
let scanned = db.scan(None, None).unwrap().len();
println!(
"after ingest {batch}: missing_via_get={} scanned={scanned} horizon_props ok",
missing.len()
);
println!("{}", db.get_property("regolith.sstables").unwrap());
}
for batch in 0..5usize {
let missing = (0..64)
.filter(|i| {
db.get(format!("ing_{batch:04}_{i:03}").as_bytes())
.unwrap()
.is_none()
})
.count();
println!("final: batch {batch} missing_via_get={missing}");
}
println!("scan len = {}", db.scan(None, None).unwrap().len());
}
#[test]
fn one_plain_write_between_ingests() {
let dir = TempDir::new().unwrap();
let staging = TempDir::new().unwrap();
let opts = Options {
write_buffer_size: 32 * 1024,
..Options::default()
};
let db = Db::open(dir.path(), opts.clone()).unwrap();
for batch in 0..5usize {
db.put(format!("plain{batch}").as_bytes(), b"p").unwrap();
let path = staging.path().join(format!("ing_{batch}.sst"));
build(&path, batch, &opts);
db.ingest_external_files(
std::slice::from_ref(&path),
IngestOptions {
snapshot_consistency: false,
..IngestOptions::default()
},
)
.unwrap();
for i in 0..64 {
let k = format!("ing_{batch:04}_{i:03}");
assert_eq!(
db.get(k.as_bytes()).unwrap(),
Some(format!("v{batch}").into_bytes()),
"batch {batch} key {i} invisible right after ingest"
);
}
}
println!("{}", db.get_property("regolith.sstables").unwrap());
}
#[test]
fn cold_cache_per_ingest() {
let dir = TempDir::new().unwrap();
let staging = TempDir::new().unwrap();
let opts = Options {
write_buffer_size: 32 * 1024,
..Options::default()
};
for batch in 0..5usize {
let path = staging.path().join(format!("ing_{batch}.sst"));
build(&path, batch, &opts);
let db = Db::open(dir.path(), opts.clone()).unwrap();
db.ingest_external_files(
std::slice::from_ref(&path),
IngestOptions {
snapshot_consistency: false,
..IngestOptions::default()
},
)
.unwrap();
db.close().unwrap();
}
let db = Db::open(dir.path(), opts).unwrap();
for batch in 0..5usize {
let missing = (0..64)
.filter(|i| {
db.get(format!("ing_{batch:04}_{i:03}").as_bytes())
.unwrap()
.is_none()
})
.count();
println!("cold cache: batch {batch} missing_via_get={missing}");
}
println!(
"cold cache: scan len = {}",
db.scan(None, None).unwrap().len()
);
}