1#![deny(unsafe_code)]
2
3use std::sync::Arc;
4
5use arc_swap::ArcSwap;
6use imbl::OrdMap;
7use tokio::sync::OwnedMutexGuard;
8
9use crate::error::Error;
10
11pub struct Tx<K, V> {
12 pub(crate) closed: bool,
13 pub(crate) writable: bool,
14 pub(crate) imm_data: OrdMap<K, V>,
15 pub(crate) lst_data: Arc<ArcSwap<OrdMap<K, V>>>,
16 pub(crate) writ_mux: Option<OwnedMutexGuard<()>>,
17}
18
19impl<K, V> Tx<K, V>
20where
21 K: Ord + Clone,
22 V: Eq + Clone,
23{
24 pub(crate) fn new(
25 data_ptr: Arc<ArcSwap<OrdMap<K, V>>>,
26 writable: bool,
27 guard: Option<OwnedMutexGuard<()>>,
28 ) -> Tx<K, V> {
29 Tx {
30 writable,
31 closed: false,
32 imm_data: (*(*data_ptr.load())).clone(),
33 lst_data: data_ptr.clone(),
34 writ_mux: guard,
35 }
36 }
37
38 pub fn closed(&self) -> bool {
39 self.closed
40 }
41
42 pub fn rollback(&mut self) -> Result<(), Error> {
43 if self.closed {
44 return Err(Error::TxClosed);
45 }
46
47 self.closed = true;
48
49 if let Some(lock) = &self.writ_mux.take() {
50 drop(lock);
51 }
52
53 Ok(())
54 }
55
56 pub fn commit(&mut self) -> Result<(), Error> {
57 if self.closed {
58 return Err(Error::TxClosed);
59 }
60
61 if !self.writable {
62 return Err(Error::TxNotWritable);
63 }
64
65 self.closed = true;
66
67 self.lst_data.store(Arc::new(self.imm_data.clone()));
68
69 if let Some(lock) = &self.writ_mux.take() {
70 drop(lock);
71 }
72
73 Ok(())
74 }
75
76 pub fn exists(&self, key: K) -> Result<bool, Error> {
77 if self.closed {
78 return Err(Error::TxClosed);
79 }
80
81 Ok(self.imm_data.contains_key(&key))
82 }
83
84 pub fn get(&self, key: K) -> Result<Option<V>, Error> {
85 if self.closed {
86 return Err(Error::TxClosed);
87 }
88
89 Ok(self.imm_data.get(&key).cloned())
90 }
91
92 pub fn set(&mut self, key: K, value: V) -> Result<(), Error> {
93 if self.closed {
94 return Err(Error::TxClosed);
95 }
96
97 if !self.writable {
98 return Err(Error::TxNotWritable);
99 }
100
101 self.imm_data.insert(key, value);
102
103 Ok(())
104 }
105
106 pub fn del(&mut self, key: K) -> Result<(), Error> {
107 if self.closed {
108 return Err(Error::TxClosed);
109 }
110
111 if !self.writable {
112 return Err(Error::TxNotWritable);
113 }
114
115 self.imm_data.remove(&key);
116
117 Ok(())
118 }
119}