cfx_executor/state/state_object/
cache_layer.rs1use super::{AccountEntry, OverlayAccount, RequireFields, State};
6use crate::{state::overlay_account::AccountEntryWithWarm, unwrap_or_return};
7use cfx_statedb::{
8 Error as DbErrorKind, Result as DbResult, StateDb, StateDbExt,
9};
10use cfx_types::{Address, AddressSpaceUtil, AddressWithSpace, U256};
11use parking_lot::{
12 MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLockReadGuard,
13 RwLockWriteGuard,
14};
15use std::collections::{
16 hash_map::Entry::{Occupied, Vacant},
17 HashMap,
18};
19
20pub type AccountReadGuard<'a> = MappedRwLockReadGuard<'a, OverlayAccount>;
21pub type AccountWriteGuard<'a> = MappedRwLockWriteGuard<'a, OverlayAccount>;
22
23impl State {
24 pub(super) fn read_account_lock(
26 &self, address: &AddressWithSpace,
27 ) -> DbResult<Option<AccountReadGuard<'_>>> {
28 self.read_account_ext_lock(address, RequireFields::None)
29 }
30
31 pub(super) fn read_native_account_lock(
33 &self, address: &Address,
34 ) -> DbResult<Option<AccountReadGuard<'_>>> {
35 self.read_account_lock(&address.with_native_space())
36 }
37
38 pub(super) fn read_account_ext_lock(
42 &self, address: &AddressWithSpace, require: RequireFields,
43 ) -> DbResult<Option<AccountReadGuard<'_>>> {
44 let mut cache = self.cache.write();
45
46 let account_entry = Self::fetch_account_mut(
47 &mut cache,
48 &self.committed_cache,
49 &self.db,
50 address,
51 require,
52 )?;
53
54 self.copy_cache_entry_to_checkpoint(*address, account_entry);
55
56 Ok(if !account_entry.is_db_absent() {
57 Some(RwLockReadGuard::map(
58 RwLockWriteGuard::downgrade(cache),
59 |cache| cache.get(address).unwrap().account().unwrap(),
60 ))
61 } else {
62 None
63 })
64 }
65
66 pub(super) fn prefetch(
69 &self, address: &AddressWithSpace, require: RequireFields,
70 ) -> DbResult<()> {
71 if let Some(account_entry) = self.cache.read().get(address) {
74 if let Some(account) = account_entry.account() {
75 if !account.should_load_ext_fields(require) {
76 return Ok(());
79 }
80 } else {
81 return Ok(());
83 }
84 }
85
86 let mut account_entry =
96 AccountEntry::new_loaded(self.db.get_account(address)?);
97 Self::load_account_ext_fields(require, &mut account_entry, &self.db)?;
98
99 self.cache
103 .write()
104 .insert(*address, account_entry.with_warm(false));
105 Ok(())
106 }
107}
108
109impl State {
110 pub fn write_account_lock(
112 &self, address: &AddressWithSpace,
113 ) -> DbResult<AccountWriteGuard<'_>> {
114 self.write_account_ext_lock(address, RequireFields::None)
115 }
116
117 pub(super) fn write_native_account_lock(
119 &self, address: &Address,
120 ) -> DbResult<AccountWriteGuard<'_>> {
121 self.write_account_lock(&address.with_native_space())
122 }
123
124 pub(super) fn write_account_ext_lock(
128 &self, address: &AddressWithSpace, require: RequireFields,
129 ) -> DbResult<AccountWriteGuard<'_>> {
130 fn no_account_is_an_error(
131 address: &AddressWithSpace,
132 ) -> DbResult<OverlayAccount> {
133 bail!(DbErrorKind::IncompleteDatabase(address.address));
134 }
135 self.write_account_inner(address, require, no_account_is_an_error)
136 }
137
138 pub(super) fn write_account_or_new_lock(
142 &self, address: &AddressWithSpace,
143 ) -> DbResult<AccountWriteGuard<'_>> {
144 fn init_if_no_account(
145 address: &AddressWithSpace,
146 ) -> DbResult<OverlayAccount> {
147 Ok(OverlayAccount::new_basic(address, U256::zero()))
156 }
157 self.write_account_inner(
158 address,
159 RequireFields::None,
160 init_if_no_account,
161 )
162 }
163
164 fn write_account_inner<F>(
168 &self, address: &AddressWithSpace, require: RequireFields, default: F,
169 ) -> DbResult<AccountWriteGuard<'_>>
170 where F: Fn(&AddressWithSpace) -> DbResult<OverlayAccount> {
171 let mut cache = self.cache.write();
172
173 let account_entry = Self::fetch_account_mut(
174 &mut cache,
175 &self.committed_cache,
176 &self.db,
177 address,
178 require,
179 )?;
180
181 self.copy_cache_entry_to_checkpoint(*address, account_entry);
183
184 if let AccountEntry::Cached(_, dirty_bit) = &mut account_entry.entry {
186 *dirty_bit = true;
187 } else {
188 account_entry.entry = AccountEntry::new_dirty(default(address)?);
189 }
190
191 Ok(RwLockWriteGuard::map(cache, |c| {
192 c.get_mut(address)
193 .expect("Entry known to exist in the cache.")
194 .dirty_account_mut()
195 .expect("Required account must exist.")
196 }))
197 }
198}
199
200impl State {
201 fn fetch_account_mut<'a>(
204 cache: &'a mut HashMap<AddressWithSpace, AccountEntryWithWarm>,
205 committed_cache: &'a HashMap<AddressWithSpace, AccountEntry>,
206 db: &StateDb, address: &AddressWithSpace, require: RequireFields,
207 ) -> DbResult<&'a mut AccountEntryWithWarm> {
208 let account_entry = match cache.entry(*address) {
209 Occupied(e) => e.into_mut(),
210 Vacant(e) => {
211 let entry = match committed_cache.get(address) {
212 Some(committed) => committed.clone_from_committed_cache(),
213 None => {
214 let address = *e.key();
215 AccountEntry::new_loaded(db.get_account(&address)?)
216 }
217 };
218 e.insert(entry.with_warm(false))
222 }
223 };
224 Self::load_account_ext_fields(require, &mut account_entry.entry, db)?;
225 Ok(account_entry)
226 }
227
228 fn load_account_ext_fields(
230 require: RequireFields, account_entry: &mut AccountEntry, db: &StateDb,
231 ) -> DbResult<()> {
232 let account = unwrap_or_return!(account_entry.account_mut(), Ok(()));
233
234 if !account.should_load_ext_fields(require) {
235 return Ok(());
236 }
237
238 match require {
239 RequireFields::None => Ok(()),
240 RequireFields::Code => account.cache_code(db),
241 RequireFields::DepositList => account.cache_ext_fields(
242 true, false, db,
245 ),
246 RequireFields::VoteStakeList => account.cache_ext_fields(
247 false, true, db,
250 ),
251 }
252 }
253}