diff options
author | Alex <alex@adnab.me> | 2024-03-15 13:17:53 +0000 |
---|---|---|
committer | Alex <alex@adnab.me> | 2024-03-15 13:17:53 +0000 |
commit | fd2e19bf1bf301bc03aa29ffa3fe1e71008cbe50 (patch) | |
tree | c92172dee172941c3daf32a08927f8ebab0ded9e /src/db | |
parent | a80ce6ab5ad9834c3721eeb4f626d53c9a8bb1f4 (diff) | |
parent | 8cf3d24875d41d79ab08d637cd38d2a5b9e527dd (diff) | |
download | garage-fd2e19bf1bf301bc03aa29ffa3fe1e71008cbe50.tar.gz garage-fd2e19bf1bf301bc03aa29ffa3fe1e71008cbe50.zip |
Merge pull request 'metadata db snapshotting' (#775) from db-snapshot into main
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/775
Diffstat (limited to 'src/db')
-rw-r--r-- | src/db/Cargo.toml | 2 | ||||
-rw-r--r-- | src/db/lib.rs | 12 | ||||
-rw-r--r-- | src/db/lmdb_adapter.rs | 10 | ||||
-rw-r--r-- | src/db/sled_adapter.rs | 8 | ||||
-rw-r--r-- | src/db/sqlite_adapter.rs | 12 |
5 files changed, 43 insertions, 1 deletions
diff --git a/src/db/Cargo.toml b/src/db/Cargo.toml index d7c89620..324de74c 100644 --- a/src/db/Cargo.toml +++ b/src/db/Cargo.toml @@ -17,7 +17,7 @@ hexdump.workspace = true tracing.workspace = true heed = { workspace = true, optional = true } -rusqlite = { workspace = true, optional = true } +rusqlite = { workspace = true, optional = true, features = ["backup"] } sled = { workspace = true, optional = true } [dev-dependencies] diff --git a/src/db/lib.rs b/src/db/lib.rs index 0fb457ce..7f19172f 100644 --- a/src/db/lib.rs +++ b/src/db/lib.rs @@ -19,6 +19,7 @@ use core::ops::{Bound, RangeBounds}; use std::borrow::Cow; use std::cell::Cell; +use std::path::PathBuf; use std::sync::Arc; use err_derive::Error; @@ -48,6 +49,12 @@ pub type TxValueIter<'a> = Box<dyn std::iter::Iterator<Item = TxOpResult<(Value, #[error(display = "{}", _0)] pub struct Error(pub Cow<'static, str>); +impl From<std::io::Error> for Error { + fn from(e: std::io::Error) -> Error { + Error(format!("IO: {}", e).into()) + } +} + pub type Result<T> = std::result::Result<T, Error>; #[derive(Debug, Error)] @@ -129,6 +136,10 @@ impl Db { } } + pub fn snapshot(&self, path: &PathBuf) -> Result<()> { + self.0.snapshot(path) + } + pub fn import(&self, other: &Db) -> Result<()> { let existing_trees = self.list_trees()?; if !existing_trees.is_empty() { @@ -325,6 +336,7 @@ pub(crate) trait IDb: Send + Sync { fn engine(&self) -> String; fn open_tree(&self, name: &str) -> Result<usize>; fn list_trees(&self) -> Result<Vec<String>>; + fn snapshot(&self, path: &PathBuf) -> Result<()>; fn get(&self, tree: usize, key: &[u8]) -> Result<Option<Value>>; fn len(&self, tree: usize) -> Result<usize>; diff --git a/src/db/lmdb_adapter.rs b/src/db/lmdb_adapter.rs index 59fa132d..4b131aff 100644 --- a/src/db/lmdb_adapter.rs +++ b/src/db/lmdb_adapter.rs @@ -3,6 +3,7 @@ use core::ptr::NonNull; use std::collections::HashMap; use std::convert::TryInto; +use std::path::PathBuf; use std::sync::{Arc, RwLock}; use heed::types::ByteSlice; @@ -102,6 +103,15 @@ impl IDb for LmdbDb { Ok(ret2) } + fn snapshot(&self, to: &PathBuf) -> Result<()> { + std::fs::create_dir_all(to)?; + let mut path = to.clone(); + path.push("data.mdb"); + self.db + .copy_to_path(path, heed::CompactionOption::Disabled)?; + Ok(()) + } + // ---- fn get(&self, tree: usize, key: &[u8]) -> Result<Option<Value>> { diff --git a/src/db/sled_adapter.rs b/src/db/sled_adapter.rs index 84f2001b..c34b4d81 100644 --- a/src/db/sled_adapter.rs +++ b/src/db/sled_adapter.rs @@ -2,6 +2,7 @@ use core::ops::Bound; use std::cell::Cell; use std::collections::HashMap; +use std::path::PathBuf; use std::sync::{Arc, RwLock}; use sled::transaction::{ @@ -96,6 +97,13 @@ impl IDb for SledDb { Ok(trees) } + fn snapshot(&self, to: &PathBuf) -> Result<()> { + let to_db = sled::open(to)?; + let export = self.db.export(); + to_db.import(export); + Ok(()) + } + // ---- fn get(&self, tree: usize, key: &[u8]) -> Result<Option<Value>> { diff --git a/src/db/sqlite_adapter.rs b/src/db/sqlite_adapter.rs index 9f967c66..827f3cc3 100644 --- a/src/db/sqlite_adapter.rs +++ b/src/db/sqlite_adapter.rs @@ -2,6 +2,7 @@ use core::ops::Bound; use std::borrow::BorrowMut; use std::marker::PhantomPinned; +use std::path::PathBuf; use std::pin::Pin; use std::ptr::NonNull; use std::sync::{Arc, Mutex, MutexGuard}; @@ -119,6 +120,17 @@ impl IDb for SqliteDb { Ok(trees) } + fn snapshot(&self, to: &PathBuf) -> Result<()> { + fn progress(p: rusqlite::backup::Progress) { + let percent = (p.pagecount - p.remaining) * 100 / p.pagecount; + info!("Sqlite snapshot progres: {}%", percent); + } + let this = self.0.lock().unwrap(); + this.db + .backup(rusqlite::DatabaseName::Main, to, Some(progress))?; + Ok(()) + } + // ---- fn get(&self, tree: usize, key: &[u8]) -> Result<Option<Value>> { |