| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- /* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- use std::collections::{btree_map::Iter, BTreeMap};
- use sled::{
- transaction::{ConflictableTransactionError, TransactionError},
- Batch, IVec, Transactional,
- };
- #[derive(Debug, PartialEq)]
- struct CacheNotFoundError;
- struct TreeCache(BTreeMap<IVec, IVec>);
- impl TreeCache {
- fn new() -> Self {
- Self(BTreeMap::new())
- }
- fn contains_key(&self, key: &IVec) -> bool {
- self.0.contains_key(key)
- }
- fn get(&self, key: &IVec) -> Option<IVec> {
- self.0.get(key).cloned()
- }
- fn insert(&mut self, key: IVec, value: IVec) -> Option<IVec> {
- self.0.insert(key, value)
- }
- fn remove(&mut self, key: &IVec) -> Option<IVec> {
- self.0.remove(key)
- }
- fn iter(&self) -> Iter<'_, IVec, IVec> {
- self.0.iter()
- }
- }
- /// We instantiate an overlay on top of a `sled::Tree` directly.
- pub struct TreeOverlay {
- tree: sled::Tree,
- cache: TreeCache,
- removed: BTreeMap<IVec, IVec>,
- }
- impl TreeOverlay {
- pub fn new(db: &sled::Tree) -> Self {
- Self { tree: db.clone(), cache: TreeCache::new(), removed: BTreeMap::new() }
- }
- pub fn contains_key(&self, key: &[u8]) -> Result<bool, sled::Error> {
- if self.removed.contains_key::<IVec>(&key.into()) {
- return Ok(false)
- }
- if self.cache.contains_key(&key.into()) || self.tree.contains_key(key)? {
- return Ok(true)
- }
- Ok(false)
- }
- pub fn get(&self, key: &[u8]) -> Result<Option<IVec>, sled::Error> {
- if self.removed.contains_key::<IVec>(&key.into()) {
- return Ok(None)
- }
- if let Some(v) = self.cache.get(&key.into()) {
- return Ok(Some(v.clone()))
- }
- self.tree.get(key)
- }
- pub fn insert(&mut self, key: &[u8], value: &[u8]) -> Result<Option<IVec>, sled::Error> {
- let mut prev: Option<IVec> = self.cache.insert(key.into(), value.into());
- if self.removed.contains_key::<IVec>(&key.into()) {
- self.removed.remove(key);
- return Ok(None)
- }
- if prev.is_none() {
- prev = self.tree.get::<IVec>(key.into())?;
- }
- Ok(prev)
- }
- pub fn remove(&mut self, key: &[u8]) -> Result<Option<IVec>, sled::Error> {
- if self.removed.contains_key::<IVec>(&key.into()) {
- return Ok(None)
- }
- self.removed.insert(key.into(), vec![].into());
- Ok(self.cache.remove(&key.into()))
- }
- pub fn aggregate(&self) -> Option<sled::Batch> {
- if self.cache.0.is_empty() && self.removed.is_empty() {
- return None
- }
- let mut batch = Batch::default();
- for (k, v) in self.cache.iter() {
- batch.insert(k, v);
- }
- for k in self.removed.keys() {
- batch.remove(k);
- }
- Some(batch)
- }
- }
- /// We instantiate overlays on top of requested
- /// sled tree keys.
- pub struct SledOverlay2 {
- db: sled::Db,
- trees: BTreeMap<IVec, sled::Tree>,
- caches: BTreeMap<IVec, TreeOverlay>,
- }
- impl SledOverlay2 {
- pub fn new(db: &sled::Db, trees_keys: &[&str]) -> Result<Self, sled::Error> {
- let mut trees = BTreeMap::new();
- let mut caches = BTreeMap::new();
- for tree_key in trees_keys {
- let tree = db.open_tree(tree_key)?;
- let cache = TreeOverlay::new(&tree);
- trees.insert(tree_key.clone().into(), tree.clone());
- caches.insert(tree_key.clone().into(), cache);
- }
- Ok(Self { db: db.clone(), trees, caches })
- }
- fn get_cache(&self, tree_key: IVec) -> Result<&TreeOverlay, sled::Error> {
- if let Some(v) = self.caches.get(&tree_key) {
- return Ok(v)
- }
- Err(sled::Error::CollectionNotFound(tree_key.clone()))
- }
- fn get_cache_mut(&mut self, tree_key: IVec) -> Result<&mut TreeOverlay, sled::Error> {
- if let Some(v) = self.caches.get_mut(&tree_key) {
- return Ok(v)
- }
- Err(sled::Error::CollectionNotFound(tree_key.clone()))
- }
- pub fn contains_key(&self, tree_key: &str, key: &[u8]) -> Result<bool, sled::Error> {
- let cache = self.get_cache(tree_key.clone().into())?;
- cache.contains_key(key)
- }
- pub fn get(&self, tree_key: &str, key: &[u8]) -> Result<Option<IVec>, sled::Error> {
- let cache = self.get_cache(tree_key.clone().into())?;
- cache.get(key)
- }
- pub fn insert(
- &mut self,
- tree_key: &str,
- key: &[u8],
- value: &[u8],
- ) -> Result<Option<IVec>, sled::Error> {
- let cache = self.get_cache_mut(tree_key.clone().into())?;
- cache.insert(key, value)
- }
- pub fn remove(&mut self, tree_key: &str, key: &[u8]) -> Result<Option<IVec>, sled::Error> {
- let cache = self.get_cache_mut(tree_key.clone().into())?;
- cache.remove(key)
- }
- pub fn execute(&mut self) -> Result<(), TransactionError<sled::Error>> {
- let mut trees = vec![];
- let mut batches = vec![];
- for (key, tree) in &self.trees {
- let cache = self.get_cache(key.clone())?;
- if let Some(batch) = cache.aggregate() {
- trees.push(tree);
- batches.push(batch);
- }
- }
- trees.transaction(|trees| {
- for (index, tree) in trees.iter().enumerate() {
- tree.apply_batch(&batches[index])?;
- }
- Ok::<(), ConflictableTransactionError<sled::Error>>(())
- })?;
- self.db.flush()?;
- Ok(())
- }
- }
|