This repository has been archived by the owner on Jan 22, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
/
Copy pathslot_stats.rs
90 lines (80 loc) · 2.51 KB
/
slot_stats.rs
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
use {
crate::blockstore_meta::SlotMeta, bitflags::bitflags, lru::LruCache, solana_sdk::clock::Slot,
};
const SLOTS_STATS_CACHE_CAPACITY: usize = 300;
macro_rules! get_mut_entry (
($cache:expr, $key:expr) => (
match $cache.get_mut(&$key) {
Some(entry) => entry,
None => {
$cache.put($key, SlotStats::default());
$cache.get_mut(&$key).unwrap()
}
}
);
);
#[derive(Copy, Clone, Debug)]
pub(crate) enum ShredSource {
Turbine,
Repaired,
Recovered,
}
bitflags! {
#[derive(Default)]
struct SlotFlags: u8 {
const DEAD = 0b00000001;
const FULL = 0b00000010;
const ROOTED = 0b00000100;
}
}
#[derive(Default)]
struct SlotStats {
flags: SlotFlags,
num_repaired: usize,
num_recovered: usize,
}
pub(crate) struct SlotsStats(LruCache<Slot, SlotStats>);
impl Default for SlotsStats {
fn default() -> Self {
// LruCache::unbounded because capacity is enforced manually.
Self(LruCache::unbounded())
}
}
impl SlotsStats {
pub(crate) fn add_shred(&mut self, slot: Slot, source: ShredSource) {
let entry = get_mut_entry!(self.0, slot);
match source {
ShredSource::Turbine => (),
ShredSource::Repaired => entry.num_repaired += 1,
ShredSource::Recovered => entry.num_recovered += 1,
}
self.maybe_evict_cache();
}
pub(crate) fn set_full(&mut self, slot_meta: &SlotMeta) {
let total_time_ms =
solana_sdk::timing::timestamp().saturating_sub(slot_meta.first_shred_timestamp);
let last_index = slot_meta
.last_index
.and_then(|ix| i64::try_from(ix).ok())
.unwrap_or(-1);
let entry = get_mut_entry!(self.0, slot_meta.slot);
if !entry.flags.contains(SlotFlags::FULL) {
datapoint_info!(
"shred_insert_is_full",
("total_time_ms", total_time_ms, i64),
("slot", slot_meta.slot, i64),
("last_index", last_index, i64),
("num_repaired", entry.num_repaired, i64),
("num_recovered", entry.num_recovered, i64),
);
}
entry.flags |= SlotFlags::FULL;
self.maybe_evict_cache();
}
fn maybe_evict_cache(&mut self) {
while self.0.len() > SLOTS_STATS_CACHE_CAPACITY {
let (_slot, _entry) = self.0.pop_lru().unwrap();
// TODO: submit metrics for (slot, entry).
}
}
}