aboutsummaryrefslogtreecommitdiffstats
path: root/log_db/src/common.rs
diff options
context:
space:
mode:
Diffstat (limited to 'log_db/src/common.rs')
-rw-r--r--log_db/src/common.rs51
1 files changed, 38 insertions, 13 deletions
diff --git a/log_db/src/common.rs b/log_db/src/common.rs
index e379364..bf949c2 100644
--- a/log_db/src/common.rs
+++ b/log_db/src/common.rs
@@ -7,6 +7,7 @@ use std::fs::{self, metadata, File};
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::thread;
+use thiserror::Error;
use uuid::Uuid;
// For Unix-like systems
@@ -29,6 +30,18 @@ pub fn metadata_filename(num: u16) -> String {
format!("metadata.{}", num)
}
+#[derive(Debug, Error)]
+pub enum DBError {
+ #[error("lock request failed: {0}")]
+ LockRequestError(#[from] LockRequestError),
+ #[error("validation failed: {0}")]
+ ValidationError(String),
+ #[error("consistency check failed: {0}")]
+ ConsistencyError(String),
+ #[error("unexpected IO error: {0}")]
+ IOError(#[from] io::Error),
+}
+
/// LogKey is a packed struct that contains:
/// - a log segment number (16 bits)
/// - a log index within the segment (48 bits)
@@ -667,11 +680,10 @@ pub fn read_metadata_header(metadata_file: &mut fs::File) -> Result<MetadataHead
Ok(header)
}
-pub fn validate_metadata_header(header: &MetadataHeader) -> Result<(), io::Error> {
+pub fn validate_metadata_header(header: &MetadataHeader) -> Result<(), DBError> {
if header.version != 1 {
- return Err(io::Error::new(
- io::ErrorKind::InvalidData,
- "Unsupported metadata file version",
+ return Err(DBError::ValidationError(
+ "Unsupported metadata file version".to_owned(),
));
}
@@ -773,7 +785,19 @@ pub fn ensure_active_metadata_is_valid(
}
}
-pub fn is_exclusive_lock_requested(data_dir: &Path) -> Result<bool, io::Error> {
+const LOCK_WAIT_MAX_MS: u64 = 100;
+
+#[derive(Error, Debug)]
+pub enum LockRequestError {
+ #[error("lock request file was removed unexpectedly")]
+ LockRequestFileRemoved,
+ #[error("timed out while waiting for a lock, max wait time: {0} ms")]
+ TimedOut(u64),
+ #[error("unexpected IO error: {0}")]
+ IOError(#[from] io::Error),
+}
+
+pub fn is_exclusive_lock_requested(data_dir: &Path) -> Result<bool, LockRequestError> {
let lock_request_path = data_dir.join(EXCL_LOCK_REQUEST_FILENAME);
let lock_request_file = fs::OpenOptions::new()
.create(true)
@@ -787,16 +811,14 @@ pub fn is_exclusive_lock_requested(data_dir: &Path) -> Result<bool, io::Error> {
if e.kind() == lock_contended_error().kind() {
return Ok(true);
}
- return Err(e);
+ return Err(LockRequestError::IOError(e));
}
+
Ok(_) => {
// Check that the exclusive lock request file is still the same as the one we opened
if !is_file_same_as_path(&lock_request_file, &lock_request_path)? {
// The lock request file has been removed
- return Err(io::Error::new(
- io::ErrorKind::Other,
- "Lock request file was removed unexpectedly",
- ));
+ return Err(LockRequestError::LockRequestFileRemoved);
}
lock_request_file.unlock()?;
@@ -805,8 +827,7 @@ pub fn is_exclusive_lock_requested(data_dir: &Path) -> Result<bool, io::Error> {
}
}
-pub fn request_shared_lock(data_dir: &Path, file: &mut fs::File) -> Result<(), io::Error> {
- const SHARED_LOCK_WAIT_MAX_MS: u64 = 100;
+pub fn request_shared_lock(data_dir: &Path, file: &mut fs::File) -> Result<(), LockRequestError> {
let mut timeout = 5;
loop {
if is_exclusive_lock_requested(data_dir)? {
@@ -815,7 +836,11 @@ pub fn request_shared_lock(data_dir: &Path, file: &mut fs::File) -> Result<(), i
timeout
);
thread::sleep(std::time::Duration::from_millis(timeout));
- timeout = std::cmp::min(timeout * 2, SHARED_LOCK_WAIT_MAX_MS);
+ timeout *= 2;
+
+ if timeout > LOCK_WAIT_MAX_MS {
+ return Err(LockRequestError::TimedOut(LOCK_WAIT_MAX_MS));
+ }
} else {
file.lock_shared()?;
return Ok(());