aboutsummaryrefslogtreecommitdiff
path: root/kv
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-02-05 20:31:55 +0100
committermetamuffin <metamuffin@disroot.org>2026-02-05 20:31:55 +0100
commit65ca3f3450d0067668111f6e13cc3089768c9efe (patch)
tree89dceed4f711d25ff2763e18a4be7e1a59e79507 /kv
parent1af0468788c0a592a76398206e6c7479384853ec (diff)
downloadjellything-65ca3f3450d0067668111f6e13cc3089768c9efe.tar
jellything-65ca3f3450d0067668111f6e13cc3089768c9efe.tar.bz2
jellything-65ca3f3450d0067668111f6e13cc3089768c9efe.tar.zst
remove read/write distinction for kv transactions; traitify database
Diffstat (limited to 'kv')
-rw-r--r--kv/src/lib.rs16
-rw-r--r--kv/src/memory.rs37
-rw-r--r--kv/src/redb.rs46
-rw-r--r--kv/src/rocksdb.rs30
4 files changed, 19 insertions, 110 deletions
diff --git a/kv/src/lib.rs b/kv/src/lib.rs
index 939391c..83f2635 100644
--- a/kv/src/lib.rs
+++ b/kv/src/lib.rs
@@ -18,22 +18,12 @@ pub use anyhow;
use anyhow::Result;
-pub type WriteTxnFunction = dyn FnMut(&mut dyn WriteTransaction) -> Result<()>;
-pub type ReadTxnFunction = dyn FnMut(&dyn ReadTransaction) -> Result<()>;
-
-pub trait Database: Send + Sync + 'static {
- fn write_transaction(
- &self,
- f: &mut dyn FnMut(&mut dyn WriteTransaction) -> Result<()>,
- ) -> Result<()>;
- fn read_transaction(&self, f: &mut dyn FnMut(&dyn ReadTransaction) -> Result<()>)
- -> Result<()>;
+pub trait Store: Send + Sync + 'static {
+ fn transaction(&self, f: &mut dyn FnMut(&mut dyn Transaction) -> Result<()>) -> Result<()>;
}
-pub trait WriteTransaction: ReadTransaction {
+pub trait Transaction {
fn set(&mut self, key: &[u8], value: &[u8]) -> Result<()>;
fn del(&mut self, key: &[u8]) -> Result<()>;
-}
-pub trait ReadTransaction {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn iter<'a>(
&'a self,
diff --git a/kv/src/memory.rs b/kv/src/memory.rs
index ad13350..1e8d1c3 100644
--- a/kv/src/memory.rs
+++ b/kv/src/memory.rs
@@ -4,11 +4,11 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::{Database, ReadTransaction, WriteTransaction};
+use crate::{Store, Transaction};
use anyhow::Result;
use std::{
collections::BTreeMap,
- sync::{RwLock, RwLockReadGuard, RwLockWriteGuard},
+ sync::{RwLock, RwLockWriteGuard},
};
type MemdbInner = BTreeMap<Vec<u8>, Vec<u8>>;
@@ -18,21 +18,12 @@ pub fn new() -> Memory {
Default::default()
}
-impl Database for Memory {
- fn write_transaction(
- &self,
- f: &mut dyn FnMut(&mut dyn WriteTransaction) -> Result<()>,
- ) -> Result<()> {
+impl Store for Memory {
+ fn transaction(&self, f: &mut dyn FnMut(&mut dyn Transaction) -> Result<()>) -> Result<()> {
f(&mut self.write().unwrap())
}
- fn read_transaction(
- &self,
- f: &mut dyn FnMut(&dyn ReadTransaction) -> Result<()>,
- ) -> Result<()> {
- f(&self.read().unwrap())
- }
}
-impl WriteTransaction for RwLockWriteGuard<'_, MemdbInner> {
+impl Transaction for RwLockWriteGuard<'_, MemdbInner> {
fn set(&mut self, key: &[u8], value: &[u8]) -> Result<()> {
self.insert(key.to_vec(), value.to_vec());
Ok(())
@@ -41,24 +32,6 @@ impl WriteTransaction for RwLockWriteGuard<'_, MemdbInner> {
self.remove(key);
Ok(())
}
-}
-impl ReadTransaction for RwLockWriteGuard<'_, MemdbInner> {
- fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
- Ok((**self).get(key).cloned())
- }
- fn iter<'a>(
- &'a self,
- key: &[u8],
- reverse: bool,
- ) -> Result<Box<dyn Iterator<Item = Result<Vec<u8>>> + 'a>> {
- Ok(if reverse {
- Box::new(self.range(key.to_vec()..).map(|e| Ok(e.0.to_vec())))
- } else {
- Box::new(self.range(..=key.to_vec()).rev().map(|e| Ok(e.0.to_vec())))
- })
- }
-}
-impl ReadTransaction for RwLockReadGuard<'_, MemdbInner> {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
Ok((**self).get(key).cloned())
}
diff --git a/kv/src/redb.rs b/kv/src/redb.rs
index e43fdfb..094acb9 100644
--- a/kv/src/redb.rs
+++ b/kv/src/redb.rs
@@ -4,22 +4,20 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::{Database, ReadTransaction, WriteTransaction};
use anyhow::Result;
-use redb::{AccessGuard, ReadableDatabase, ReadableTable, StorageError, Table, TableDefinition};
+use redb::{AccessGuard, ReadableTable, StorageError, Table, TableDefinition};
use std::path::Path;
+use crate::{Store, Transaction};
+
const TABLE: TableDefinition<&[u8], &[u8]> = TableDefinition::new("kv");
pub fn new(path: &Path) -> Result<redb::Database> {
Ok(redb::Database::create(path)?)
}
-impl Database for redb::Database {
- fn write_transaction(
- &self,
- f: &mut dyn FnMut(&mut dyn WriteTransaction) -> Result<()>,
- ) -> Result<()> {
+impl Store for redb::Database {
+ fn transaction(&self, f: &mut dyn FnMut(&mut dyn Transaction) -> Result<()>) -> Result<()> {
let txn = self.begin_write()?;
let mut table = txn.open_table(TABLE)?;
f(&mut table)?;
@@ -27,17 +25,9 @@ impl Database for redb::Database {
txn.commit()?;
Ok(())
}
- fn read_transaction(
- &self,
- f: &mut dyn FnMut(&dyn ReadTransaction) -> Result<()>,
- ) -> Result<()> {
- let mut txn = self.begin_read()?;
- f(&mut txn)?;
- Ok(())
- }
}
-impl WriteTransaction for Table<'_, &[u8], &[u8]> {
+impl Transaction for Table<'_, &[u8], &[u8]> {
fn set(&mut self, key: &[u8], value: &[u8]) -> Result<()> {
self.insert(key, value)?;
Ok(())
@@ -46,8 +36,6 @@ impl WriteTransaction for Table<'_, &[u8], &[u8]> {
self.remove(key)?;
Ok(())
}
-}
-impl ReadTransaction for Table<'_, &[u8], &[u8]> {
fn get<'a>(&'a self, key: &[u8]) -> Result<Option<Vec<u8>>> {
match ReadableTable::get(self, key)? {
Some(v) => Ok(Some(v.value().to_vec())),
@@ -69,25 +57,3 @@ impl ReadTransaction for Table<'_, &[u8], &[u8]> {
})
}
}
-impl ReadTransaction for redb::ReadTransaction {
- fn get<'a>(&'a self, key: &[u8]) -> Result<Option<Vec<u8>>> {
- match self.open_table(TABLE)?.get(key)? {
- Some(v) => Ok(Some(v.value().to_vec())),
- None => Ok(None),
- }
- }
- fn iter<'a>(
- &'a self,
- key: &[u8],
- reverse: bool,
- ) -> Result<Box<dyn Iterator<Item = Result<Vec<u8>>> + 'a>> {
- let k = |e: Result<(AccessGuard<'_, &[u8]>, AccessGuard<'_, &[u8]>), StorageError>| {
- e.map(|e| e.0.value().to_vec()).map_err(|e| e.into())
- };
- Ok(if reverse {
- Box::new(self.open_table(TABLE)?.range(..=key)?.rev().map(k))
- } else {
- Box::new(self.open_table(TABLE)?.range(key..)?.map(k))
- })
- }
-}
diff --git a/kv/src/rocksdb.rs b/kv/src/rocksdb.rs
index 8aa559c..c78dd96 100644
--- a/kv/src/rocksdb.rs
+++ b/kv/src/rocksdb.rs
@@ -8,17 +8,14 @@ use anyhow::Result;
use rocksdb::{Direction, ErrorKind, IteratorMode, OptimisticTransactionDB};
use std::path::Path;
-use crate::{BlobStorage, Database, ReadTransaction, WriteTransaction};
+use crate::{BlobStorage, Store, Transaction};
pub fn new(path: &Path) -> Result<OptimisticTransactionDB> {
Ok(OptimisticTransactionDB::open_default(path)?)
}
-impl Database for OptimisticTransactionDB {
- fn write_transaction(
- &self,
- f: &mut dyn FnMut(&mut dyn WriteTransaction) -> Result<()>,
- ) -> Result<()> {
+impl Store for OptimisticTransactionDB {
+ fn transaction(&self, f: &mut dyn FnMut(&mut dyn Transaction) -> Result<()>) -> Result<()> {
loop {
let mut txn = self.transaction();
f(&mut txn)?;
@@ -29,33 +26,16 @@ impl Database for OptimisticTransactionDB {
}
}
}
- fn read_transaction(
- &self,
- f: &mut dyn FnMut(&dyn ReadTransaction) -> Result<()>,
- ) -> Result<()> {
- loop {
- let txn = self.transaction();
- f(&txn)?;
- match txn.commit() {
- Ok(()) => break Ok(()),
- Err(e) if e.kind() == ErrorKind::Busy => continue,
- Err(e) => return Err(e.into()),
- }
- }
- }
}
-impl WriteTransaction for rocksdb::Transaction<'_, OptimisticTransactionDB> {
- fn set(&mut self, key: &[u8], value: &[u8]) -> Result<()> {
+impl Transaction for rocksdb::Transaction<'_, OptimisticTransactionDB> {
+ fn set(&mut self, key: &[u8], value: &[u8]) -> Result<()> {
Ok(self.put(key, value)?)
}
fn del(&mut self, key: &[u8]) -> Result<()> {
Ok(self.delete(key)?)
}
-}
-
-impl ReadTransaction for rocksdb::Transaction<'_, OptimisticTransactionDB> {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
Ok(self.get(key)?)
}