diff --git a/src/database/abstraction.rs b/src/database/abstraction.rs index a3c6ccfd..ea5fd424 100644 --- a/src/database/abstraction.rs +++ b/src/database/abstraction.rs @@ -41,6 +41,17 @@ pub trait KeyValueDatabaseEngine: Send + Sync { fn memory_usage(&self) -> Result { Ok("Current database engine does not support memory usage reporting.".to_owned()) } + fn clear_caches(&self) {} + + fn export(&self, _exporter: &mut Box) -> Result<()> { + unimplemented!() + } +} + +pub trait KvExport { + fn start_index(&mut self, name: &str) -> Result<()>; + fn key_value(&mut self, key: &[u8], value: &[u8]) -> Result<()>; + fn end_index(&mut self, name: &str) -> Result<()>; } pub trait KvTree: Send + Sync { diff --git a/src/database/abstraction/persy.rs b/src/database/abstraction/persy.rs index da7d4cf0..563607a7 100644 --- a/src/database/abstraction/persy.rs +++ b/src/database/abstraction/persy.rs @@ -1,6 +1,6 @@ use crate::{ database::{ - abstraction::{watchers::Watchers, KeyValueDatabaseEngine, KvTree}, + abstraction::{watchers::Watchers, KeyValueDatabaseEngine, KvExport, KvTree}, Config, }, Result, @@ -45,6 +45,22 @@ impl KeyValueDatabaseEngine for Arc { fn flush(&self) -> Result<()> { Ok(()) } + + fn export(&self, exporter: &mut Box) -> Result<()> { + let snapshot = self.persy.snapshot()?; + let indexes = snapshot.list_indexes()?; + for (index, _) in indexes { + exporter.start_index(&index)?; + let data = snapshot.range::(&index, ..)?; + for (key, values) in data { + for value in values { + exporter.key_value(&key, &value)?; + } + } + exporter.end_index(&index)?; + } + Ok(()) + } } pub struct PersyTree { diff --git a/src/database/abstraction/rocksdb.rs b/src/database/abstraction/rocksdb.rs index cf77e3dd..a7afae5b 100644 --- a/src/database/abstraction/rocksdb.rs +++ b/src/database/abstraction/rocksdb.rs @@ -1,4 +1,4 @@ -use super::{super::Config, watchers::Watchers, KeyValueDatabaseEngine, KvTree}; +use super::{super::Config, watchers::Watchers, KeyValueDatabaseEngine, KvExport, KvTree}; use crate::{utils, Result}; use std::{ future::Future, @@ -11,6 +11,7 @@ pub struct Engine { max_open_files: i32, cache: rocksdb::Cache, old_cfs: Vec, + database_path: String, } pub struct RocksDbEngineTree<'a> { @@ -85,6 +86,7 @@ impl KeyValueDatabaseEngine for Arc { max_open_files: config.rocksdb_max_open_files, cache: rocksdb_cache, old_cfs: cfs, + database_path: config.database_path.clone(), })) } @@ -126,6 +128,30 @@ impl KeyValueDatabaseEngine for Arc { self.cache.get_pinned_usage() as f64 / 1024.0 / 1024.0, )) } + + fn export(&self, exporter: &mut Box) -> Result<()> { + let snapshot = self.rocks.snapshot(); + let indexes = rocksdb::DBWithThreadMode::::list_cf( + &rocksdb::Options::default(), + &self.database_path, + ) + .unwrap(); + for index in indexes { + if let Some(handle) = self.rocks.cf_handle(&index) { + exporter.start_index(&index)?; + let data = snapshot.iterator_cf(&handle, rocksdb::IteratorMode::Start); + for ele in data { + if let Ok((key, value)) = ele { + exporter.key_value(&key, &value)?; + } + } + exporter.end_index(&index)?; + } + } + Ok(()) + } + + fn clear_caches(&self) {} } impl RocksDbEngineTree<'_> {