common/database/
transactions.rs1use crate::database::Store;
4use crate::database::db_context::DbContext;
5use crate::snapshot::StoreSnapshot;
6use anyhow::{Ok, Result, bail};
7use std::sync::Arc;
8
9use crate::types;
10
11pub struct Transaction {
12 store: Arc<Store>,
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 crate::database::rope_helpers::recompute_all_frame_byte_ranges(&self.store);
43 if let Some(sp) = self.savepoint.take() {
45 self.store.discard_savepoint(sp);
46 }
47 Ok(())
48 }
49
50 pub fn rollback(&mut self) -> Result<()> {
51 if !self.is_write {
52 bail!("Cannot rollback a read transaction");
53 }
54 if let Some(sp) = self.savepoint.take() {
56 self.store.restore_savepoint(sp);
57 }
58 Ok(())
59 }
60
61 pub fn end_read_transaction(&mut self) -> Result<()> {
62 if self.is_write {
63 bail!("Cannot end a write transaction as read");
64 }
65 Ok(())
66 }
67
68 pub fn get_store(&self) -> &Store {
69 &self.store
70 }
71
72 pub fn create_savepoint(&self) -> Result<types::Savepoint> {
73 if !self.is_write {
74 bail!("Cannot create savepoint on a read transaction");
75 }
76 Ok(self.store.create_savepoint())
77 }
78
79 pub fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
80 if !self.is_write {
81 bail!("Cannot restore savepoint on a read transaction");
82 }
83 self.store.restore_savepoint(savepoint);
84 Ok(())
85 }
86
87 pub fn snapshot_store(&self) -> StoreSnapshot {
89 self.store.store_snapshot()
90 }
91
92 pub fn restore_store(&self, snap: &StoreSnapshot) {
94 self.store.restore_store_snapshot(snap);
95 }
96}
97
98impl Drop for Transaction {
99 fn drop(&mut self) {
100 if let Some(sp) = self.savepoint.take() {
103 self.store.restore_savepoint(sp);
104 }
105 }
106}