aboutsummaryrefslogtreecommitdiff
path: root/database/src
diff options
context:
space:
mode:
Diffstat (limited to 'database/src')
-rw-r--r--database/src/backends/memory.rs2
-rw-r--r--database/src/backends/mod.rs13
-rw-r--r--database/src/backends/rocksdb.rs2
-rw-r--r--database/src/indices/mod.rs6
-rw-r--r--database/src/indices/order.rs16
-rw-r--r--database/src/lib.rs42
-rw-r--r--database/src/table.rs64
-rw-r--r--database/src/transaction.rs42
8 files changed, 128 insertions, 59 deletions
diff --git a/database/src/backends/memory.rs b/database/src/backends/memory.rs
index 2f19ce6..f1952a3 100644
--- a/database/src/backends/memory.rs
+++ b/database/src/backends/memory.rs
@@ -20,7 +20,7 @@ impl KV for Memory {
self.0.write().unwrap().insert(key.to_vec(), value.to_vec());
Ok(())
}
- fn get<'a>(&'a self, key: &[u8]) -> Result<Option<Vec<u8>>> {
+ fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
Ok(self.0.read().unwrap().get(key).cloned())
}
fn del(&self, key: &[u8]) -> Result<()> {
diff --git a/database/src/backends/mod.rs b/database/src/backends/mod.rs
index b6d3770..814cc50 100644
--- a/database/src/backends/mod.rs
+++ b/database/src/backends/mod.rs
@@ -8,7 +8,9 @@ pub mod memory;
pub mod redb;
pub mod rocksdb;
-use anyhow::Result;
+use crate::backends::{memory::Memory, redb::Redb, rocksdb::Rocksdb};
+use anyhow::{Result, bail};
+use std::{path::Path, sync::Arc};
pub trait KV {
fn set(&self, key: &[u8], value: &[u8]) -> Result<()>;
@@ -17,3 +19,12 @@ pub trait KV {
fn next(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn prev(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
}
+
+pub fn create_backend(driver: &str, path: &Path) -> Result<Arc<dyn KV>> {
+ Ok(match driver {
+ "rocksdb" => Arc::new(Rocksdb::new(path)?),
+ "redb" => Arc::new(Redb::new(path)?),
+ "memory" => Arc::new(Memory::new()),
+ _ => bail!("unknown db driver"),
+ })
+}
diff --git a/database/src/backends/rocksdb.rs b/database/src/backends/rocksdb.rs
index f4ed55b..31229a9 100644
--- a/database/src/backends/rocksdb.rs
+++ b/database/src/backends/rocksdb.rs
@@ -25,7 +25,7 @@ impl KV for Rocksdb {
fn set(&self, key: &[u8], value: &[u8]) -> Result<()> {
Ok(self.db.put(key, value)?)
}
- fn get<'a>(&'a self, key: &[u8]) -> Result<Option<Vec<u8>>> {
+ fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
Ok(self.db.get(key)?)
}
fn del(&self, key: &[u8]) -> Result<()> {
diff --git a/database/src/indices/mod.rs b/database/src/indices/mod.rs
index 48e91a9..5856254 100644
--- a/database/src/indices/mod.rs
+++ b/database/src/indices/mod.rs
@@ -4,14 +4,14 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::backends::KV;
+use crate::{backends::KV, table::RowNum};
use anyhow::Result;
pub mod order;
pub trait Index<T> {
- fn add(&self, db: &dyn KV, id: u64, val: &T) -> Result<()>;
- fn remove(&self, db: &dyn KV, id: u64, val: &T) -> Result<()>;
+ fn add(&self, db: &dyn KV, row: RowNum, val: &T) -> Result<()>;
+ fn remove(&self, db: &dyn KV, row: RowNum, val: &T) -> Result<()>;
fn compare(&self, before: &T, after: &T) -> bool {
let _ = (before, after);
true
diff --git a/database/src/indices/order.rs b/database/src/indices/order.rs
index 852342d..04fb975 100644
--- a/database/src/indices/order.rs
+++ b/database/src/indices/order.rs
@@ -4,27 +4,17 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::{Table, backends::KV, indices::Index};
+use crate::{backends::KV, indices::Index, table::Table};
use anyhow::Result;
-use std::sync::Arc;
pub struct OrderIndex<T> {
id: u32,
value: fn(&T) -> [u8; 8],
- db: Arc<dyn KV>,
}
impl<T: 'static> OrderIndex<T> {
pub fn new(table: &mut Table<T>, id: u32, value: fn(&T) -> [u8; 8]) -> Self {
- table.indices.push(Box::new(Self {
- id,
- value,
- db: table.db.clone(),
- }));
- Self {
- id,
- value,
- db: table.db.clone(),
- }
+ table.indices.push(Box::new(Self { id, value }));
+ Self { id, value }
}
fn key(&self, id: u64, val: &T) -> Vec<u8> {
let mut key = Vec::new();
diff --git a/database/src/lib.rs b/database/src/lib.rs
index 828761e..7618fe7 100644
--- a/database/src/lib.rs
+++ b/database/src/lib.rs
@@ -4,45 +4,7 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use anyhow::{Result, bail};
-
-use crate::{
- backends::{KV, memory::Memory, redb::Redb, rocksdb::Rocksdb},
- indices::Index,
-};
-use std::{path::Path, sync::Arc};
-
pub mod backends;
pub mod indices;
-
-pub struct Database {
- storage: Arc<dyn KV>,
-}
-
-impl Database {
- pub fn new(driver: &str, path: &Path) -> Result<Self> {
- Ok(Self {
- storage: match driver {
- "rocksdb" => Arc::new(Rocksdb::new(path)?),
- "redb" => Arc::new(Redb::new(path)?),
- "memory" => Arc::new(Memory::new()),
- _ => bail!("unknown db driver"),
- },
- })
- }
-}
-
-pub struct Table<T> {
- id: u32,
- indices: Vec<Box<dyn Index<T>>>,
- db: Arc<dyn KV>,
-}
-impl<T> Table<T> {
- pub fn new(db: &Database, id: u32) -> Self {
- Self {
- id,
- indices: Vec::new(),
- db: db.storage.clone(),
- }
- }
-}
+pub mod table;
+pub mod transaction;
diff --git a/database/src/table.rs b/database/src/table.rs
new file mode 100644
index 0000000..8c6b724
--- /dev/null
+++ b/database/src/table.rs
@@ -0,0 +1,64 @@
+/*
+ This file is part of jellything (https://codeberg.org/metamuffin/jellything)
+ which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
+ Copyright (C) 2025 metamuffin <metamuffin.org>
+*/
+
+use crate::{backends::KV, indices::Index};
+use anyhow::Result;
+use serde::{Serialize, de::DeserializeOwned};
+
+pub type RowNum = u64;
+
+pub struct Table<T> {
+ id: u32,
+ pub(crate) indices: Vec<Box<dyn Index<T>>>,
+}
+impl<T: Serialize + DeserializeOwned> Table<T> {
+ pub fn new(id: u32) -> Self {
+ Self {
+ id,
+ indices: Vec::new(),
+ }
+ }
+ fn key(&self, row: RowNum) -> Vec<u8> {
+ let mut key = Vec::new();
+ key.extend(self.id.to_be_bytes());
+ key.extend(row.to_be_bytes());
+ key
+ }
+ pub fn insert(&self, db: &dyn KV, entry: T) -> Result<RowNum> {
+ let mut id_counter = db
+ .get(&self.id.to_be_bytes())?
+ .map(|k| k.as_slice().try_into().map(RowNum::from_be_bytes).ok())
+ .flatten()
+ .unwrap_or(0);
+ let row = id_counter;
+ id_counter += 1;
+ db.set(&self.id.to_be_bytes(), &id_counter.to_be_bytes())?;
+
+ db.set(&self.key(row), &serde_json::to_vec(&entry)?)?;
+
+ for idx in &self.indices {
+ idx.add(db, row, &entry)?;
+ }
+
+ Ok(id_counter)
+ }
+ pub fn get(&self, db: &dyn KV, row: RowNum) -> Result<Option<T>> {
+ Ok(db
+ .get(&self.key(row))?
+ .map(|v| serde_json::from_slice(&v))
+ .transpose()?)
+ }
+ pub fn remove(&self, db: &dyn KV, row: RowNum) -> Result<bool> {
+ let Some(entry) = self.get(db, row)? else {
+ return Ok(false);
+ };
+ for idx in &self.indices {
+ idx.remove(db, row, &entry)?;
+ }
+ db.del(&self.key(row))?;
+ Ok(true)
+ }
+}
diff --git a/database/src/transaction.rs b/database/src/transaction.rs
new file mode 100644
index 0000000..c0e89b7
--- /dev/null
+++ b/database/src/transaction.rs
@@ -0,0 +1,42 @@
+/*
+ This file is part of jellything (https://codeberg.org/metamuffin/jellything)
+ which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
+ Copyright (C) 2025 metamuffin <metamuffin.org>
+*/
+
+use crate::backends::KV;
+use anyhow::Result;
+use std::sync::Arc;
+
+pub struct TransactionController {
+ db: Arc<dyn KV>,
+}
+impl TransactionController {
+ pub fn transact(&self, tx: impl Fn(&mut Transaction) -> Result<()>) -> Result<()> {
+ tx(&mut Transaction {
+ db: self.db.clone(),
+ })?;
+ Ok(())
+ }
+}
+
+pub struct Transaction {
+ db: Arc<dyn KV>,
+}
+impl KV for Transaction {
+ fn set(&self, key: &[u8], value: &[u8]) -> Result<()> {
+ self.db.set(key, value)
+ }
+ fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
+ self.db.get(key)
+ }
+ fn del(&self, key: &[u8]) -> Result<()> {
+ self.db.del(key)
+ }
+ fn next(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
+ self.db.next(key)
+ }
+ fn prev(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
+ self.db.prev(key)
+ }
+}