Ret FileLock from BGSave to unlock before flush_db

next
Sayan Nandan 3 years ago
parent 5df31287da
commit 1180de3b71

@ -223,6 +223,22 @@ impl Data {
}
}
pub enum SyncFileLock {
FileLock(flock::FileLock),
FileLockTaskHandle(tokio::task::JoinHandle<diskstore::flock::FileLock>),
}
impl SyncFileLock {
pub async fn unlock(self) -> std::io::Result<()> {
match self {
SyncFileLock::FileLock(mut lock) => lock.unlock(),
SyncFileLock::FileLockTaskHandle(lock) => {
lock.await?.unlock()
}
}
}
}
impl CoreDB {
#[cfg(debug_assertions)]
#[allow(dead_code)] // This has been kept for debugging purposes, so we'll suppress this lint
@ -286,7 +302,7 @@ impl CoreDB {
bgsave: BGSave,
snapshot_cfg: SnapshotConfig,
restore_file: Option<PathBuf>,
) -> TResult<(Self, Option<flock::FileLock>)> {
) -> TResult<(Self, SyncFileLock)> {
let coretable = diskstore::get_saved(restore_file)?;
let mut background_tasks: usize = 0;
if !bgsave.is_disabled() {
@ -325,11 +341,11 @@ impl CoreDB {
let lock = flock::FileLock::lock("data.bin")
.map_err(|e| format!("Failed to acquire lock on data file with error '{}'", e))?;
if bgsave.is_disabled() {
Ok((db, Some(lock)))
Ok((db, SyncFileLock::FileLock(lock)))
} else {
// Spawn the BGSAVE service in a separate task
tokio::spawn(diskstore::bgsave_scheduler(db.clone(), bgsave, lock));
Ok((db, None))
let data = tokio::spawn(diskstore::bgsave_scheduler(db.clone(), bgsave, lock));
Ok((db, SyncFileLock::FileLockTaskHandle(data)))
}
}
/// Create an empty in-memory table

@ -391,12 +391,10 @@ pub async fn run(
}
}
server.finish_with_termsig().await;
if let Some(mut lock) = lock {
if let Err(e) = lock.unlock() {
if let Err(e) = lock.unlock().await {
log::error!("Failed to release lock on data file with '{}'", e);
process::exit(0x100);
}
}
} else {
if let Err(e) = flush_db!(db) {
log::error!("Failed to flush data to disk with '{}'", e);
loop {
@ -415,6 +413,7 @@ pub async fn run(
log::info!("Successfully saved data to disk");
}
terminal::write_info("Goodbye :)\n").unwrap();
}
}
/// This is a **test only** function

@ -133,6 +133,14 @@ mod tests {
file.unlock().unwrap();
file.unlock().unwrap();
}
#[cfg(windows)]
#[test]
fn test_windows_lock_and_then_unlock() {
let mut file = FileLock::lock("data4.bin").unwrap();
file.unlock().unwrap();
let mut file2 = FileLock::lock("data4.bin").unwrap();
file.unlock().unwrap();
}
}
#[cfg(windows)]

@ -36,7 +36,6 @@ use std::fs;
use std::io::{ErrorKind, Write};
use std::iter::FromIterator;
use std::path::PathBuf;
use std::process;
use std::time::Duration;
use tokio::time;
pub mod flock;
@ -115,14 +114,14 @@ pub async fn bgsave_scheduler(
handle: coredb::CoreDB,
bgsave_cfg: BGSave,
mut file: flock::FileLock,
) {
) -> flock::FileLock {
let duration = match bgsave_cfg {
BGSave::Disabled => {
// So, there's no BGSAVE! Looks like our user's pretty confident
// that there won't be any power failures! Never mind, we'll just
// shut down the BGSAVE task, and immediately return
handle.shared.bgsave_task.notified().await;
return;
return file;
}
BGSave::Enabled(duration) => {
// If we're here - the user doesn't trust his power supply or just values
@ -142,17 +141,5 @@ pub async fn bgsave_scheduler(
handle.shared.bgsave_task.notified().await
}
}
if let Err(e) = tokio::task::spawn_blocking(move || {
if let Err(e) = file.unlock() {
log::error!("Failed to release lock on data file with error '{}'", e);
process::exit(0x100);
}
})
.await
{
log::error!(
"Blocking operation to unlock data file failed with error '{}'",
e
);
}
file
}

Loading…
Cancel
Save