diff --git a/utils/src/pm_tree/sled_adapter.rs b/utils/src/pm_tree/sled_adapter.rs index 96dc16c..c35533f 100644 --- a/utils/src/pm_tree/sled_adapter.rs +++ b/utils/src/pm_tree/sled_adapter.rs @@ -2,29 +2,51 @@ use pmtree::*; use sled::Db as Sled; use std::collections::HashMap; +use std::thread; +use std::time::Duration; pub struct SledDB(Sled); +impl SledDB { + fn new_with_tries(config: ::Config, tries: u32) -> PmtreeResult { + // If we've tried more than 10 times, we give up and return an error. + if tries >= 10 { + return Err(PmtreeErrorKind::DatabaseError( + DatabaseErrorKind::CustomError(format!( + "Cannot create database: exceeded maximum retry attempts. {config:#?}" + )), + )); + } + match config.open() { + Ok(db) => Ok(SledDB(db)), + Err(e) if e.to_string().contains("WouldBlock") => { + // try till the fd is freed + // sleep for 10^tries milliseconds, then recursively try again + thread::sleep(Duration::from_millis(10u64.pow(tries))); + Self::new_with_tries(config, tries + 1) + } + Err(e) => { + // On any other error, we return immediately. + Err(PmtreeErrorKind::DatabaseError( + DatabaseErrorKind::CustomError(format!( + "Cannot create database: {e} {config:#?}" + )), + )) + } + } + } +} + impl Database for SledDB { type Config = sled::Config; fn new(config: Self::Config) -> PmtreeResult { - let db: Sled = match config.open() { - Ok(db) => db, - Err(e) => { - return Err(PmtreeErrorKind::DatabaseError( - DatabaseErrorKind::CustomError(format!( - "Cannot create database: {e} {config:#?}", - )), - )) - } - }; - - Ok(SledDB(db)) + let db = Self::new_with_tries(config, 0)?; + Ok(db) } fn load(config: Self::Config) -> PmtreeResult { - let db: Sled = match sled::open(&config.path) { + let db = match config.open() { Ok(db) => db, Err(e) => { return Err(PmtreeErrorKind::DatabaseError(