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 commit(&mut self) -> Result<()> {
37 if !self.is_write {
38 bail!("Cannot commit a read transaction");
39 }
40 if let Some(sp) = self.savepoint.take() {
42 self.store.discard_savepoint(sp);
43 }
44 Ok(())
45 }
46
47 pub fn rollback(&mut self) -> Result<()> {
48 if !self.is_write {
49 bail!("Cannot rollback a read transaction");
50 }
51 if let Some(sp) = self.savepoint.take() {
53 self.store.restore_savepoint(sp);
54 }
55 Ok(())
56 }
57
58 pub fn end_read_transaction(&mut self) -> Result<()> {
59 if self.is_write {
60 bail!("Cannot end a write transaction as read");
61 }
62 Ok(())
63 }
64
65 pub fn get_store(&self) -> &HashMapStore {
66 &self.store
67 }
68
69 pub fn create_savepoint(&self) -> Result<types::Savepoint> {
70 if !self.is_write {
71 bail!("Cannot create savepoint on a read transaction");
72 }
73 Ok(self.store.create_savepoint())
74 }
75
76 pub fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
77 if !self.is_write {
78 bail!("Cannot restore savepoint on a read transaction");
79 }
80 self.store.restore_savepoint(savepoint);
81 Ok(())
82 }
83
84 pub fn snapshot_store(&self) -> StoreSnapshot {
86 self.store.store_snapshot()
87 }
88
89 pub fn restore_store(&self, snap: &StoreSnapshot) {
91 self.store.restore_store_snapshot(snap);
92 }
93}
94
95impl Drop for Transaction {
96 fn drop(&mut self) {
97 if let Some(sp) = self.savepoint.take() {
100 self.store.restore_savepoint(sp);
101 }
102 }
103}