Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ ratatui = "0.29"
crossterm = "0.28"
rand = "0.8"
lru = "0.12"
fs2 = "0.4"

# ============================================
# RUST-MAGIC-LINTER - Maximum Preset
Expand Down
20 changes: 20 additions & 0 deletions node/src/storage/sharded/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ impl SegmentWriter {
pub struct Storage {
data_dir: PathBuf,
peer_cache_dir: PathBuf,
/// Exclusive lock on `{data_dir}/.lock` — prevents a second process from
/// opening the same data directory. Held for the lifetime of this struct;
/// released automatically on drop.
_lock_file: fs::File,
meta: Mutex<MetaState>,
shards: Mutex<HashMap<u64, Arc<Mutex<ShardState>>>>,
peer_cache: Mutex<HashMap<String, StoredPeer>>,
Expand Down Expand Up @@ -484,6 +488,13 @@ impl Storage {
tracing::info!(data_dir = %config.data_dir.display(), "storage open: starting");

fs::create_dir_all(&config.data_dir).wrap_err("failed to create data dir")?;

let lock_path = config.data_dir.join(".lock");
let lock_file =
fs::File::create(&lock_path).wrap_err("failed to create lock file")?;
fs2::FileExt::try_lock_exclusive(&lock_file)
.wrap_err("data directory is already in use by another shinode process")?;

let peer_cache_dir = config
.peer_cache_dir
.clone()
Expand Down Expand Up @@ -708,6 +719,7 @@ impl Storage {
Ok(Self {
data_dir: config.data_dir.clone(),
peer_cache_dir,
_lock_file: lock_file,
meta: Mutex::new(meta),
shards: Mutex::new(shards),
peer_cache: Mutex::new(peer_cache),
Expand All @@ -724,6 +736,14 @@ impl Storage {
return Ok(RepairReport { shards: vec![] });
}

// Acquire exclusive lock to prevent concurrent repair / sync
let lock_path = config.data_dir.join(".lock");
let lock_file =
fs::File::create(&lock_path).wrap_err("failed to create lock file")?;
fs2::FileExt::try_lock_exclusive(&lock_file)
.wrap_err("data directory is already in use by another shinode process")?;
let _lock_file = lock_file; // hold until end of function

let shards_root = shards_dir(&config.data_dir);
if !shards_root.exists() {
return Ok(RepairReport { shards: vec![] });
Expand Down