Skip to content

Commit

Permalink
Add Raft storage engine trait.
Browse files Browse the repository at this point in the history
This wrapper trait allows using a trait object for the Raft log storage
engine, which prevents leaking generics through the Raft implementation.
  • Loading branch information
erikgrinaker committed Nov 14, 2023
1 parent 22a1152 commit 2de3988
Showing 1 changed file with 57 additions and 1 deletion.
58 changes: 57 additions & 1 deletion src/raft/log.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::error::{Error, Result};
use crate::storage::log::Range;
use crate::storage::{bincode, log};
use crate::storage::{self, bincode, log};

use ::log::debug;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -192,6 +192,62 @@ impl Log {
}
}

/// A Raft log storage engine. This is a wrapper trait around storage::Engine
/// with a blanket implementation, to make it object-safe (this is otherwise
/// prevented by the generic scan() method). This wrapper allows Log to use a
/// trait object for the engine, which prevents leaking generics throughout the
/// Raft implementation.
///
/// TODO: Consider getting rid of this and using generics throughout.
pub trait Engine: std::fmt::Display + Send + Sync {
fn delete(&mut self, key: &[u8]) -> Result<()>;

fn flush(&mut self) -> Result<()>;

fn get(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>>;

#[allow(clippy::type_complexity)]
fn scan(
&mut self,
from: std::ops::Bound<Vec<u8>>,
to: std::ops::Bound<Vec<u8>>,
) -> Box<dyn DoubleEndedIterator<Item = Result<(Vec<u8>, Vec<u8>)>> + '_>;

fn set(&mut self, key: &[u8], value: Vec<u8>) -> Result<()>;

fn status(&mut self) -> Result<storage::engine::Status>;
}

impl<E: storage::engine::Engine> Engine for E {
fn delete(&mut self, key: &[u8]) -> Result<()> {
self.delete(key)
}

fn flush(&mut self) -> Result<()> {
self.flush()
}

fn get(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
self.get(key)
}

fn scan(
&mut self,
from: std::ops::Bound<Vec<u8>>,
to: std::ops::Bound<Vec<u8>>,
) -> Box<dyn DoubleEndedIterator<Item = Result<(Vec<u8>, Vec<u8>)>> + '_> {
Box::new(self.scan((from, to)))
}

fn set(&mut self, key: &[u8], value: Vec<u8>) -> Result<()> {
self.set(key, value)
}

fn status(&mut self) -> Result<storage::engine::Status> {
self.status()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 2de3988

Please sign in to comment.