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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Wrappers for the raw nnint syscalls
//!
//! A storage location can be in the following states:
//! - Never before set
//! - Set to an item-type other than nnint
//! - Set to a nnint
//!
//! In the first two cases, we say that the location "does not contain a
//! nnint".
//!
//! During a transaction, pending "set" and "add" values are maintained for the
//! cell when it contains a nnint, notionally with types `Option<i128>` and
//! `i128`, respectively.
//!
//! Calling `set_add(s_opt, a)` replaces these pending values; this always
//! succeeds unless `s_opt.is_some_and(|s| s + a < 0)`.
//!
//! Calling `get_values` (without forcing) returns the pending values without
//! consulting the database. It provides a "set" value only if a set operation
//! has been used in this transaction.
//!
//! The function `get_values_force` returns the pending "set" value if
//! available, or else loads the snapshot value from the database. This aborts
//! if the location does not contain a non-negative-int.
use crate;
use crate;
use crate;
use crate::*;
/// Replace the "set" and "add" values. With `exclusive`, then request an
/// exclusive lock on the key.
///
/// This discards any values previously present. A shared write leaves the
/// key's storage flags as they are; see
/// [`sys_result::flags`](crate::sys_result::flags).
///
/// This aborts if `set_value.is_some_and(|s| s + a < 0)`.
///
/// Like [`set_add`], but report a failed write as `Err` instead of aborting.
/// Callers that pre-check the negativity constraint (so the remaining error
/// paths are host faults) use this to keep the `try_` law. A failed write
/// requests no lock.
pub
/// Get the pending "set" and "add" values.
///
/// If the storage location has not yet been loaded, this succeeds no matter
/// what is at the location (including nothing or a value of another storage
/// type).
///
/// Like [`get_values`], but report a syscall failure as `Err` instead of
/// aborting. Callers that pre-check the negativity constraint (so the
/// remaining error paths are invalid flags or host faults) use this to keep
/// the `try_` law.
pub
/// Get the pending "set" and "add" values, loading if necessary.
///
/// This behaves like `get_values`, except if the pending "set" value is
/// `None`, we instead load and return the last-committed value.
///
/// This aborts if the location does not contain a nnint.
///
/// Get the pending "set" and "add" values, loading if necessary, and
/// reporting failure as `Err` instead of aborting (the `try_` law; see the
/// [`exn`](mod@crate::exn) module docs).
///
/// This behaves like `get_values_force`, except every failure — a
/// never-written location
/// (`Err(e)` with [`e.is_storage_missing()`](LibraryExn::is_storage_missing)),
/// a value of another storage type
/// ([`kSyscallErrorCodeInvalidSyscallInput`](crate::sys::SyscallErrorCode::kSyscallErrorCodeInvalidSyscallInput)),
/// or any other syscall error — is returned as the `LibraryExn::Syscall`
/// value the non-`try_` form would have thrown.
///
// Returns an error if `force_load_set` is true and the location does not
// contain a non-negative integer.
//
// Otherwise, this always succeeds no matter what is at the location.
//