common/database/
transactions.rs1use crate::database::db_context::DbContext;
4use crate::database::hashmap_store::HashMapStore;
5use crate::snapshot::StoreSnapshot;
6use anyhow::{Ok, Result, bail};
7use std::sync::Arc;
8
9use crate::types;
10
11pub struct Transaction {
12 store: Arc<HashMapStore>,
13 is_write: bool,
14 savepoint: Option<u64>,
15}
16
17impl Transaction {
18 pub fn begin_write_transaction(db_context: &DbContext) -> Result<Transaction> {
19 let store = Arc::clone(db_context.get_store());
20 let savepoint = Some(store.create_savepoint());
21 Ok(Transaction {
22 store,
23 is_write: true,
24 savepoint,
25 })
26 }
27
28 pub fn begin_read_transaction(db_context: &DbContext) -> Result<Transaction> {
29 Ok(Transaction {
30 store: Arc::clone(db_context.get_store()),
31 is_write: false,
32 savepoint: None,
33 })
34 }
35
36 pub fn begin_frozen_read_transaction(db_context: &DbContext) -> Result<Transaction> {
44 Ok(Transaction {
45 store: Arc::new(db_context.get_store().freeze()),
46 is_write: false,
47 savepoint: None,
48 })
49 }
50
51 pub fn commit(&mut self) -> Result<()> {
52 if !self.is_write {
53 bail!("Cannot commit a read transaction");
54 }
55 if let Some(sp) = self.savepoint.take() {
57 self.store.discard_savepoint(sp);
58 }
59 Ok(())
60 }
61
62 pub fn rollback(&mut self) -> Result<()> {
63 if !self.is_write {
64 bail!("Cannot rollback a read transaction");
65 }
66 if let Some(sp) = self.savepoint.take() {
69 self.store.restore_savepoint(sp);
70 self.store.discard_savepoint(sp);
71 }
72 Ok(())
73 }
74
75 pub fn end_read_transaction(&mut self) -> Result<()> {
76 if self.is_write {
77 bail!("Cannot end a write transaction as read");
78 }
79 Ok(())
80 }
81
82 pub fn get_store(&self) -> &HashMapStore {
83 &self.store
84 }
85
86 pub fn create_savepoint(&self) -> Result<types::Savepoint> {
87 if !self.is_write {
88 bail!("Cannot create savepoint on a read transaction");
89 }
90 Ok(self.store.create_savepoint())
91 }
92
93 pub fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
94 if !self.is_write {
95 bail!("Cannot restore savepoint on a read transaction");
96 }
97 self.store.restore_savepoint(savepoint);
98 Ok(())
99 }
100
101 pub fn snapshot_store(&self) -> StoreSnapshot {
103 self.store.store_snapshot()
104 }
105
106 pub fn restore_store(&self, snap: &StoreSnapshot) {
108 self.store.restore_store_snapshot(snap);
109 }
110}
111
112impl Drop for Transaction {
113 fn drop(&mut self) {
114 if let Some(sp) = self.savepoint.take() {
118 self.store.restore_savepoint(sp);
119 self.store.discard_savepoint(sp);
120 }
121 }
122}