use lock_db::prelude::*;
fn main() {
let lm = LockManager::new();
let (account_a, account_b) = (ResourceId::new(1), ResourceId::new(2));
let (t1, t2) = (TxnId::new(1), TxnId::new(2));
assert_eq!(
lm.request(t1, account_a, LockMode::Exclusive),
Acquisition::Granted
);
assert_eq!(
lm.request(t2, account_b, LockMode::Exclusive),
Acquisition::Granted
);
println!("t1 holds account A, t2 holds account B");
match lm.request(t1, account_b, LockMode::Exclusive) {
Acquisition::Waiting => println!("t1 waits for account B"),
other => panic!("expected waiting, got {other:?}"),
}
match lm.request(t2, account_a, LockMode::Exclusive) {
Acquisition::Deadlock(deadlock) => {
println!(
"deadlock detected: cycle {:?}, aborting victim t{}",
deadlock.cycle.iter().map(|t| t.get()).collect::<Vec<_>>(),
deadlock.victim.get(),
);
let released = lm.release_all(deadlock.victim);
println!("victim released {released} locks");
let survivor = if deadlock.victim == t1 { t2 } else { t1 };
let wanted = if survivor == t1 { account_b } else { account_a };
assert_eq!(
lm.request(survivor, wanted, LockMode::Exclusive),
Acquisition::Granted
);
println!("t{} proceeds; no deadlock remains", survivor.get());
}
other => panic!("expected deadlock, got {other:?}"),
}
assert!(lm.find_deadlock().is_none());
}