/* 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 */ use crate::backends::{Db, ReadTransaction, WriteTransaction, WriteTxnFunction}; use anyhow::Result; use rocksdb::{ErrorKind, OptimisticTransactionDB}; use std::path::Path; pub struct Rocksdb { db: OptimisticTransactionDB, } impl Rocksdb { pub fn new(path: &Path) -> Result { Ok(Self { db: OptimisticTransactionDB::open_default(path)?, }) } } impl Db for Rocksdb { fn write_transaction(&self, f: &mut WriteTxnFunction) -> Result<()> { loop { let mut txn = self.db.transaction(); f(&mut txn)?; match txn.commit() { Ok(()) => break Ok(()), Err(e) if e.kind() == ErrorKind::Busy => continue, Err(e) => return Err(e.into()), } } } fn read_transaction(&self, f: &mut super::ReadTxnFunction) -> Result<()> { loop { let txn = self.db.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<()> { 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>> { Ok(self.get(key)?) } fn next(&self, key: &[u8]) -> Result>> { let mut it = self.raw_iterator(); it.seek_for_prev(key); it.next(); Ok(it.key().map(Vec::from)) } fn prev(&self, key: &[u8]) -> Result>> { let mut it = self.raw_iterator(); it.seek(key); it.prev(); Ok(it.key().map(Vec::from)) } }