use noxu_db::{DatabaseConfig, DatabaseEntry, EnvironmentConfig};
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::thread;
use std::time::Duration;
fn main() {
let dir: PathBuf =
env::var("NOXU_CRASH_DIR").expect("NOXU_CRASH_DIR must be set").into();
let mode =
env::var("NOXU_CRASH_MODE").expect("NOXU_CRASH_MODE must be set");
let env_config = EnvironmentConfig::new(dir.clone())
.with_allow_create(true)
.with_transactional(true);
let env = noxu_db::Environment::open(env_config).expect("open env");
let db_config = DatabaseConfig::new().with_allow_create(true);
let db = env.open_database(None, "test", &db_config).expect("open db");
match mode.as_str() {
"committed_then_uncommitted" => {
for i in 0u32..50 {
let txn = env.begin_transaction(None).expect("begin txn");
let key = DatabaseEntry::from_bytes(&i.to_be_bytes());
let val = DatabaseEntry::from_bytes(b"committed");
db.put(Some(&txn), &key, &val).expect("put");
txn.commit().expect("commit");
}
flag(&dir, "phase1_done");
let txn = env.begin_transaction(None).expect("begin txn");
for i in 1000u32..1050 {
let key = DatabaseEntry::from_bytes(&i.to_be_bytes());
let val = DatabaseEntry::from_bytes(b"uncommitted");
db.put(Some(&txn), &key, &val).expect("put");
}
flag(&dir, "phase2_started");
loop {
thread::sleep(Duration::from_millis(50));
}
}
"uncommitted_only" => {
let txn = env.begin_transaction(None).expect("begin txn");
let sentinel_key = DatabaseEntry::from_bytes(b"sentinel");
let sentinel_val = DatabaseEntry::from_bytes(b"ok");
db.put(Some(&txn), &sentinel_key, &sentinel_val)
.expect("put sentinel");
txn.commit().expect("commit sentinel");
flag(&dir, "sentinel_committed");
let txn = env.begin_transaction(None).expect("begin txn");
for i in 0u32..50 {
let key = DatabaseEntry::from_bytes(&i.to_be_bytes());
let val = DatabaseEntry::from_bytes(b"uncommitted");
db.put(Some(&txn), &key, &val).expect("put");
}
flag(&dir, "uncommitted_started");
loop {
thread::sleep(Duration::from_millis(50));
}
}
"ordered_commits" => {
let txn = env.begin_transaction(None).expect("begin T1");
for i in 0u32..25 {
let key = DatabaseEntry::from_bytes(&i.to_be_bytes());
let val = DatabaseEntry::from_bytes(b"t1");
db.put(Some(&txn), &key, &val).expect("put T1");
}
txn.commit().expect("commit T1");
flag(&dir, "t1_done");
let txn = env.begin_transaction(None).expect("begin T2");
for i in 100u32..125 {
let key = DatabaseEntry::from_bytes(&i.to_be_bytes());
let val = DatabaseEntry::from_bytes(b"t2");
db.put(Some(&txn), &key, &val).expect("put T2");
}
flag(&dir, "t2_started");
drop(txn); loop {
thread::sleep(Duration::from_millis(50));
}
}
"clean_then_dirty" => {
for i in 0u32..25 {
let txn = env.begin_transaction(None).expect("begin txn");
let key = DatabaseEntry::from_bytes(&i.to_be_bytes());
let val = DatabaseEntry::from_bytes(b"parity");
db.put(Some(&txn), &key, &val).expect("put");
txn.commit().expect("commit");
}
flag(&dir, "writes_done");
loop {
thread::sleep(Duration::from_millis(50));
}
}
other => panic!("Unknown NOXU_CRASH_MODE: {other}"),
}
}
fn flag(dir: &Path, name: &str) {
fs::write(dir.join(name), b"ok")
.unwrap_or_else(|e| panic!("write flag {name}: {e}"));
}