1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use_prelude!();
use collection::ScopedCollection;
use super::collection::document_id::DocumentId;
mod collection;
use marker::InvariantLifetime as TypeLevelId;
pub struct ScopedStore<'batch> {
txn: &'batch mut ffi_sdk::CWriteTransaction,
store: &'batch Store,
results: &'batch mut Vec<WriteTransactionResult>,
_txn_id: TypeLevelId<'batch>,
}
pub(super) fn with_batched_write<F>(
store: &Store,
f: F,
) -> Result<Vec<WriteTransactionResult>, super::DittoError>
where
for<'batch> F: FnOnce(ScopedStore<'batch>) -> Action<'batch>,
{
use super::*;
let hint: Option<char_p::Ref<'_>> = None;
let mut txn = unsafe { ffi_sdk::ditto_write_transaction(&*store.ditto, hint).ok()? };
let mut results = vec![];
let batch = ScopedStore {
txn: &mut *txn,
store,
results: &mut results,
_txn_id: TypeLevelId::default(),
};
match f(batch).0 {
ActionKind::Commit => {
let status = unsafe { ffi_sdk::ditto_write_transaction_commit(&*store.ditto, txn) };
if status != 0 {
return Err(DittoError::from_ffi(ErrorKind::Internal));
}
}
ActionKind::Rollback => {
unsafe { ffi_sdk::ditto_write_transaction_rollback(&*store.ditto, txn) };
}
}
Ok(results)
}
pub struct Action<'batch>(ActionKind, TypeLevelId<'batch>);
enum ActionKind {
Commit,
Rollback,
}
impl<'batch> ScopedStore<'batch> {
pub fn commit_changes(self: ScopedStore<'batch>) -> Action<'batch> {
Action(ActionKind::Commit, TypeLevelId::default())
}
pub fn revert_changes(self: ScopedStore<'batch>) -> Action<'batch> {
Action(ActionKind::Rollback, TypeLevelId::default())
}
pub fn collection<'coll>(
self: &'coll mut ScopedStore<'batch>,
collection_name: &'_ str,
) -> ScopedCollection<'coll, 'batch> {
let c_name = char_p::new(collection_name);
ScopedCollection {
batch: self,
collection_name: c_name,
}
}
}
pub struct WriteTransactionResult {
pub collection_name: char_p::Box,
pub doc_id: DocumentId,
pub kind: DocChangeKind,
}
#[derive(Debug, PartialEq, Eq)]
pub enum DocChangeKind {
Inserted,
Removed,
Evicted,
Updated,
}