test under lock contention
This commit is contained in:
parent
1c231e0fd1
commit
b1f8e8a709
4 changed files with 45 additions and 4 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -31,6 +31,7 @@ dependencies = [
|
||||||
"atomicwrites",
|
"atomicwrites",
|
||||||
"base64",
|
"base64",
|
||||||
"cargo-husky",
|
"cargo-husky",
|
||||||
|
"fail",
|
||||||
"femme",
|
"femme",
|
||||||
"fs2",
|
"fs2",
|
||||||
"glob",
|
"glob",
|
||||||
|
@ -198,6 +199,17 @@ version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fail"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3be3c61c59fdc91f5dbc3ea31ee8623122ce80057058be560654c5d410d181a6"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"rand 0.7.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "femme"
|
name = "femme"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
|
|
|
@ -9,6 +9,7 @@ license = "AGPL-3.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
atomicwrites = "0.2"
|
atomicwrites = "0.2"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
|
fail = "0.4"
|
||||||
femme = "2.1"
|
femme = "2.1"
|
||||||
fs2 = "0.4"
|
fs2 = "0.4"
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
|
@ -38,3 +39,6 @@ features = ["run-for-all", "prepush-hook", "run-cargo-check", "run-cargo-test",
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = 1
|
debug = 1
|
||||||
|
|
||||||
|
[features]
|
||||||
|
failpoints = [ "fail/failpoints" ]
|
|
@ -8,5 +8,5 @@ fi
|
||||||
cargo fmt -- --check
|
cargo fmt -- --check
|
||||||
cargo clippy --all-targets --all-features -- -D warnings
|
cargo clippy --all-targets --all-features -- -D warnings
|
||||||
cargo check --frozen
|
cargo check --frozen
|
||||||
cargo test
|
cargo test --all-targets --all-features
|
||||||
cargo test -- --ignored
|
cargo test --all-targets --all-features -- --ignored
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
#[cfg(feature = "failpoints")]
|
||||||
|
use anyhow::*;
|
||||||
|
use fail::fail_point;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use vfs::VfsPath;
|
use vfs::VfsPath;
|
||||||
|
@ -33,13 +36,13 @@ impl Lock {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_to_have_sole_lock(lock_id: Uuid, index_directory: &VfsPath) -> Result<()> {
|
fn wait_to_have_sole_lock(lock_id: Uuid, index_directory: &VfsPath) -> Result<()> {
|
||||||
Lock::create_lock_file(lock_id, index_directory)?;
|
let _ = Lock::create_lock_file(lock_id, index_directory);
|
||||||
while !Lock::sole_lock(lock_id, index_directory)? {
|
while !Lock::sole_lock(lock_id, index_directory)? {
|
||||||
let path = Lock::lock_file_path(index_directory, lock_id)?;
|
let path = Lock::lock_file_path(index_directory, lock_id)?;
|
||||||
path.remove_file()?;
|
path.remove_file()?;
|
||||||
let sleep_duration = time::Duration::from_millis((OsRng.next_u32() % 256).into());
|
let sleep_duration = time::Duration::from_millis((OsRng.next_u32() % 256).into());
|
||||||
thread::sleep(sleep_duration);
|
thread::sleep(sleep_duration);
|
||||||
Lock::create_lock_file(lock_id, index_directory)?;
|
let _ = Lock::create_lock_file(lock_id, index_directory);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -67,6 +70,7 @@ impl Lock {
|
||||||
|
|
||||||
fn create_lock_file(lock_id: Uuid, index_directory: &VfsPath) -> Result<()> {
|
fn create_lock_file(lock_id: Uuid, index_directory: &VfsPath) -> Result<()> {
|
||||||
let lock_file_path = Lock::lock_file_path(index_directory, lock_id)?;
|
let lock_file_path = Lock::lock_file_path(index_directory, lock_id)?;
|
||||||
|
fail_point!("create-lock-file", |e: Option<String>| Err(anyhow!(e.unwrap())));
|
||||||
let mut file = lock_file_path.create_file()?;
|
let mut file = lock_file_path.create_file()?;
|
||||||
let lock_id_text = lock_id.to_hyphenated().to_string();
|
let lock_id_text = lock_id.to_hyphenated().to_string();
|
||||||
let lock_id_bytes = lock_id_text.as_bytes();
|
let lock_id_bytes = lock_id_text.as_bytes();
|
||||||
|
@ -89,6 +93,11 @@ impl Drop for Lock {
|
||||||
mod must {
|
mod must {
|
||||||
use super::Lock;
|
use super::Lock;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
#[cfg(feature = "failpoints")]
|
||||||
|
use anyhow::*;
|
||||||
|
#[cfg(feature = "failpoints")]
|
||||||
|
use fail::FailScenario;
|
||||||
use vfs::{MemoryFS, VfsPath};
|
use vfs::{MemoryFS, VfsPath};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -102,4 +111,20 @@ mod must {
|
||||||
assert_eq!(entries, 0);
|
assert_eq!(entries, 0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "failpoints")]
|
||||||
|
fn be_able_to_lock_under_high_contention() -> Result<()> {
|
||||||
|
let scenario = FailScenario::setup();
|
||||||
|
fail::cfg("create-lock-file", "90%10*return(some lock file creation error)->off").map_err(|e| anyhow!(e))?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let path = MemoryFS::new().into();
|
||||||
|
let lock = Lock::lock(&path)?;
|
||||||
|
lock.release()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
scenario.teardown();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue