Skip to content

Commit 15644ca

Browse files
authored
ChainData: Allow reading rooted account state (#18)
- refactor getting the latest rooted write into newest_rooted_write() - add iter_accounts_rooted() - also add raw_account_data(), raw_slot_data() as escape hatches
1 parent a3b7391 commit 15644ca

File tree

1 file changed

+62
-33
lines changed

1 file changed

+62
-33
lines changed

connector/src/chain_data.rs

+62-33
Original file line numberDiff line numberDiff line change
@@ -133,30 +133,18 @@ impl ChainData {
133133
self.account_bytes_stored = 0;
134134

135135
for (_, writes) in self.accounts.iter_mut() {
136-
let newest_rooted_write = writes
137-
.iter()
138-
.rev()
139-
.find(|w| {
140-
w.slot <= self.newest_rooted_slot
141-
&& self
142-
.slots
143-
.get(&w.slot)
144-
.map(|s| {
145-
// sometimes we seem not to get notifications about slots
146-
// getting rooted, hence assume non-uncle slots < newest_rooted_slot
147-
// are rooted too
148-
s.status == SlotStatus::Rooted
149-
|| s.chain == self.best_chain_slot
150-
})
151-
// preserved account writes for deleted slots <= newest_rooted_slot
152-
// are expected to be rooted
153-
.unwrap_or(true)
154-
})
155-
.map(|w| w.slot)
156-
// no rooted write found: produce no effect, since writes > newest_rooted_slot are retained anyway
157-
.unwrap_or(self.newest_rooted_slot + 1);
158-
writes
159-
.retain(|w| w.slot == newest_rooted_write || w.slot > self.newest_rooted_slot);
136+
let newest_rooted_write_slot = Self::newest_rooted_write(
137+
writes,
138+
self.newest_rooted_slot,
139+
self.best_chain_slot,
140+
&self.slots,
141+
)
142+
.map(|w| w.slot)
143+
// no rooted write found: produce no effect, since writes > newest_rooted_slot are retained anyway
144+
.unwrap_or(self.newest_rooted_slot + 1);
145+
writes.retain(|w| {
146+
w.slot == newest_rooted_write_slot || w.slot > self.newest_rooted_slot
147+
});
160148
self.account_versions_stored += writes.len();
161149
self.account_bytes_stored +=
162150
writes.iter().map(|w| w.account.data().len()).sum::<usize>()
@@ -212,17 +200,32 @@ impl ChainData {
212200
.unwrap_or(write.slot <= self.newest_rooted_slot || write.slot > self.best_chain_slot)
213201
}
214202

203+
fn newest_rooted_write<'a>(
204+
writes: &'a [AccountData],
205+
newest_rooted_slot: u64,
206+
best_chain_slot: u64,
207+
slots: &HashMap<u64, SlotData>,
208+
) -> Option<&'a AccountData> {
209+
writes.iter().rev().find(|w| {
210+
w.slot <= newest_rooted_slot
211+
&& slots
212+
.get(&w.slot)
213+
.map(|s| {
214+
// sometimes we seem not to get notifications about slots
215+
// getting rooted, hence assume non-uncle slots < newest_rooted_slot
216+
// are rooted too
217+
s.status == SlotStatus::Rooted || s.chain == best_chain_slot
218+
})
219+
// preserved account writes for deleted slots <= newest_rooted_slot
220+
// are expected to be rooted
221+
.unwrap_or(true)
222+
})
223+
}
224+
215225
/// Cloned snapshot of all the most recent live writes per pubkey
216226
pub fn accounts_snapshot(&self) -> HashMap<Pubkey, AccountData> {
217-
self.accounts
218-
.iter()
219-
.filter_map(|(pubkey, writes)| {
220-
let latest_good_write = writes
221-
.iter()
222-
.rev()
223-
.find(|w| self.is_account_write_live(w))?;
224-
Some((*pubkey, latest_good_write.clone()))
225-
})
227+
self.iter_accounts()
228+
.map(|(pk, a)| (*pk, a.clone()))
226229
.collect()
227230
}
228231

@@ -237,6 +240,7 @@ impl ChainData {
237240
.ok_or_else(|| anyhow::anyhow!("account {} has no live data", pubkey))
238241
}
239242

243+
/// Iterate over the most recent live data for all stored accounts
240244
pub fn iter_accounts(&self) -> impl Iterator<Item = (&Pubkey, &AccountData)> {
241245
self.accounts.iter().filter_map(|(pk, writes)| {
242246
writes
@@ -247,6 +251,19 @@ impl ChainData {
247251
})
248252
}
249253

254+
/// Iterate over the most recent rooted data for all stored accounts
255+
pub fn iter_accounts_rooted(&self) -> impl Iterator<Item = (&Pubkey, &AccountData)> {
256+
self.accounts.iter().filter_map(|(pk, writes)| {
257+
Self::newest_rooted_write(
258+
writes,
259+
self.newest_rooted_slot,
260+
self.best_chain_slot,
261+
&self.slots,
262+
)
263+
.map(|latest_write| (pk, latest_write))
264+
})
265+
}
266+
250267
pub fn slots_count(&self) -> usize {
251268
self.slots.len()
252269
}
@@ -270,6 +287,18 @@ impl ChainData {
270287
pub fn newest_rooted_slot(&self) -> u64 {
271288
self.newest_rooted_slot
272289
}
290+
291+
pub fn newest_processed_slot(&self) -> u64 {
292+
self.newest_processed_slot
293+
}
294+
295+
pub fn raw_account_data(&self) -> &HashMap<Pubkey, Vec<AccountData>> {
296+
&self.accounts
297+
}
298+
299+
pub fn raw_slot_data(&self) -> &HashMap<u64, SlotData> {
300+
&self.slots
301+
}
273302
}
274303

275304
pub struct ChainDataMetrics {

0 commit comments

Comments
 (0)