grovedb_merk/test_utils/
temp_merk.rs1#[cfg(feature = "full")]
32use std::ops::{Deref, DerefMut};
33
34use grovedb_path::SubtreePath;
35#[cfg(feature = "full")]
36use grovedb_storage::{rocksdb_storage::test_utils::TempStorage, Storage};
37use grovedb_storage::{
38 rocksdb_storage::{PrefixedRocksDbTransactionContext, RocksDbStorage},
39 StorageBatch,
40};
41use grovedb_version::version::GroveVersion;
42
43#[cfg(feature = "full")]
44use crate::Merk;
45use crate::{tree::kv::ValueDefinedCostType, TreeType};
46
47#[cfg(feature = "full")]
48pub struct TempMerk {
50 storage: &'static TempStorage,
51 batch: &'static StorageBatch,
52 merk: Merk<PrefixedRocksDbTransactionContext<'static>>,
53 tx: &'static <RocksDbStorage as Storage<'static>>::Transaction,
54}
55
56#[cfg(feature = "full")]
57impl TempMerk {
58 pub fn new(grove_version: &GroveVersion) -> Self {
61 let storage = Box::leak(Box::new(TempStorage::new()));
62 let batch = Box::leak(Box::new(StorageBatch::new()));
63 let tx = Box::leak(Box::new(storage.start_transaction()));
64
65 let context = storage
66 .get_transactional_storage_context(SubtreePath::empty(), Some(batch), tx)
67 .unwrap();
68
69 let merk = Merk::open_base(
70 context,
71 TreeType::NormalTree,
72 None::<fn(&[u8], &GroveVersion) -> Option<ValueDefinedCostType>>,
73 grove_version,
74 )
75 .unwrap()
76 .unwrap();
77 TempMerk {
78 storage,
79 merk,
80 batch,
81 tx,
82 }
83 }
84
85 pub fn commit(&mut self, grove_version: &GroveVersion) {
87 let batch: Box<StorageBatch> =
88 unsafe { Box::from_raw(self.batch as *const _ as *mut StorageBatch) };
89 let tx: Box<<RocksDbStorage as Storage<'static>>::Transaction> = unsafe {
90 Box::from_raw(
91 self.tx as *const _ as *mut <RocksDbStorage as Storage<'static>>::Transaction,
92 )
93 };
94 self.storage
95 .commit_multi_context_batch(*batch, Some(self.tx))
96 .unwrap()
97 .expect("unable to commit batch");
98 self.storage
99 .commit_transaction(*tx)
100 .unwrap()
101 .expect("unable to commit transaction");
102 self.batch = Box::leak(Box::new(StorageBatch::new()));
103 self.tx = Box::leak(Box::new(self.storage.start_transaction()));
104 let context = self
105 .storage
106 .get_transactional_storage_context(SubtreePath::empty(), Some(self.batch), self.tx)
107 .unwrap();
108 self.merk = Merk::open_base(
109 context,
110 TreeType::NormalTree,
111 None::<fn(&[u8], &GroveVersion) -> Option<ValueDefinedCostType>>,
112 grove_version,
113 )
114 .unwrap()
115 .unwrap();
116 }
117}
118
119#[cfg(feature = "full")]
120impl Drop for TempMerk {
121 fn drop(&mut self) {
122 unsafe {
123 let batch = Box::from_raw(self.batch as *const _ as *mut StorageBatch);
124
125 let tx: Box<<RocksDbStorage as Storage<'static>>::Transaction> = Box::from_raw(
126 self.tx as *const _ as *mut <RocksDbStorage as Storage<'static>>::Transaction,
127 );
128
129 let _ = self.storage.commit_multi_context_batch(*batch, Some(&tx));
130 let _ = self.storage.commit_transaction(*tx).unwrap();
131 drop(Box::from_raw(self.storage as *const _ as *mut TempStorage));
132 }
133 }
134}
135
136#[cfg(feature = "full")]
137impl Default for TempMerk {
138 fn default() -> Self {
139 Self::new(GroveVersion::latest())
140 }
141}
142
143#[cfg(feature = "full")]
144impl Deref for TempMerk {
145 type Target = Merk<PrefixedRocksDbTransactionContext<'static>>;
146
147 fn deref(&self) -> &Merk<PrefixedRocksDbTransactionContext<'static>> {
148 &self.merk
149 }
150}
151
152#[cfg(feature = "full")]
153impl DerefMut for TempMerk {
154 fn deref_mut(&mut self) -> &mut Merk<PrefixedRocksDbTransactionContext<'static>> {
155 &mut self.merk
156 }
157}