/* 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) 2026 metamuffin */ use crate::backends::{Database, ReadTransaction, WriteTransaction, WriteTxnFunction}; use anyhow::Result; use rocksdb::{Direction, ErrorKind, IteratorMode, OptimisticTransactionDB}; use std::path::Path; pub fn new(path: &Path) -> Result { Ok(OptimisticTransactionDB::open_default(path)?) } impl Database for OptimisticTransactionDB { fn write_transaction(&self, f: &mut WriteTxnFunction) -> Result<()> { loop { let mut txn = self.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.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 iter<'a>( &'a self, key: &[u8], reverse: bool, ) -> Result>> + 'a>> { let mut iter = self.iterator(IteratorMode::Start); iter.set_mode(IteratorMode::From( key, if reverse { Direction::Reverse } else { Direction::Forward }, )); Ok(Box::new(iter.map(|e| { e.map(|(k, _)| k.into_vec()).map_err(|e| e.into()) }))) } }