gemachain_runtime/
sorted_storages.rs1use crate::accounts_db::SnapshotStorage;
2use log::*;
3use gemachain_measure::measure::Measure;
4use gemachain_sdk::clock::Slot;
5use std::ops::Range;
6
7pub struct SortedStorages<'a> {
8 range: Range<Slot>,
9 storages: Vec<Option<&'a SnapshotStorage>>,
10 slot_count: usize,
11}
12
13impl<'a> SortedStorages<'a> {
14 pub fn get(&self, slot: Slot) -> Option<&SnapshotStorage> {
15 if !self.range.contains(&slot) {
16 None
17 } else {
18 let index = (slot - self.range.start) as usize;
19 self.storages[index]
20 }
21 }
22
23 pub fn range_width(&self) -> Slot {
24 self.range.end - self.range.start
25 }
26
27 pub fn range(&self) -> &Range<Slot> {
28 &self.range
29 }
30
31 pub fn slot_count(&self) -> usize {
32 self.slot_count
33 }
34
35 pub fn new(source: &'a [SnapshotStorage]) -> Self {
39 let slots = source
40 .iter()
41 .map(|storages| {
42 let first = storages.first();
43 assert!(first.is_some(), "SnapshotStorage.is_empty()");
44 let storage = first.unwrap();
45 storage.slot() })
47 .collect::<Vec<_>>();
48 Self::new_with_slots(source.iter().zip(slots.iter()), None, None)
49 }
50
51 pub fn new_with_slots<'b>(
56 source: impl Iterator<Item = (&'a SnapshotStorage, &'b Slot)> + Clone,
57 min_slot: Option<Slot>,
59 max_slot_inclusive: Option<Slot>,
64 ) -> Self {
65 let mut min = Slot::MAX;
66 let mut max = Slot::MIN;
67 let mut adjust_min_max = |slot| {
68 min = std::cmp::min(slot, min);
69 max = std::cmp::max(slot + 1, max);
70 };
71 if let Some(slot) = min_slot {
73 adjust_min_max(slot);
74 }
75 if let Some(slot) = max_slot_inclusive {
76 adjust_min_max(slot);
77 }
78
79 let mut slot_count = 0;
80 let mut time = Measure::start("get slot");
81 let source_ = source.clone();
82 source_.for_each(|(_, slot)| {
83 slot_count += 1;
84 adjust_min_max(*slot);
85 });
86 time.stop();
87 let mut time2 = Measure::start("sort");
88 let range;
89 let mut storages;
90 if min > max {
91 range = Range::default();
92 storages = vec![];
93 } else {
94 range = Range {
95 start: min,
96 end: max,
97 };
98 let len = max - min;
99 storages = vec![None; len as usize];
100 source.for_each(|(original_storages, slot)| {
101 let index = (slot - min) as usize;
102 assert!(storages[index].is_none(), "slots are not unique"); storages[index] = Some(original_storages);
104 });
105 }
106 time2.stop();
107 debug!("SortedStorages, times: {}, {}", time.as_us(), time2.as_us());
108 Self {
109 range,
110 storages,
111 slot_count,
112 }
113 }
114}
115
116#[cfg(test)]
117pub mod tests {
118 use super::*;
119 impl<'a> SortedStorages<'a> {
120 pub fn new_debug(source: &[(&'a SnapshotStorage, Slot)], min: Slot, len: usize) -> Self {
121 let mut storages = vec![None; len];
122 let range = Range {
123 start: min,
124 end: min + len as Slot,
125 };
126 let slot_count = source.len();
127 for (storage, slot) in source {
128 storages[*slot as usize] = Some(*storage);
129 }
130
131 Self {
132 range,
133 storages,
134 slot_count,
135 }
136 }
137 }
138
139 #[test]
140 #[should_panic(expected = "SnapshotStorage.is_empty()")]
141 fn test_sorted_storages_empty() {
142 SortedStorages::new(&[Vec::new()]);
143 }
144
145 #[test]
146 #[should_panic(expected = "slots are not unique")]
147 fn test_sorted_storages_duplicate_slots() {
148 SortedStorages::new_with_slots(
149 [Vec::new(), Vec::new()].iter().zip([0, 0].iter()),
150 None,
151 None,
152 );
153 }
154
155 #[test]
156 fn test_sorted_storages_none() {
157 let result = SortedStorages::new_with_slots([].iter().zip([].iter()), None, None);
158 assert_eq!(result.range, Range::default());
159 assert_eq!(result.slot_count, 0);
160 assert_eq!(result.storages.len(), 0);
161 assert!(result.get(0).is_none());
162 }
163
164 #[test]
165 fn test_sorted_storages_1() {
166 let vec = vec![];
167 let vec_check = vec.clone();
168 let slot = 4;
169 let vecs = [vec];
170 let result = SortedStorages::new_with_slots(vecs.iter().zip([slot].iter()), None, None);
171 assert_eq!(
172 result.range,
173 Range {
174 start: slot,
175 end: slot + 1
176 }
177 );
178 assert_eq!(result.slot_count, 1);
179 assert_eq!(result.storages.len(), 1);
180 assert_eq!(result.get(slot).unwrap().len(), vec_check.len());
181 }
182
183 #[test]
184 fn test_sorted_storages_2() {
185 let vec = vec![];
186 let vec_check = vec.clone();
187 let slots = [4, 7];
188 let vecs = [vec.clone(), vec];
189 let result = SortedStorages::new_with_slots(vecs.iter().zip(slots.iter()), None, None);
190 assert_eq!(
191 result.range,
192 Range {
193 start: slots[0],
194 end: slots[1] + 1,
195 }
196 );
197 assert_eq!(result.slot_count, 2);
198 assert_eq!(result.storages.len() as Slot, slots[1] - slots[0] + 1);
199 assert!(result.get(0).is_none());
200 assert!(result.get(3).is_none());
201 assert!(result.get(5).is_none());
202 assert!(result.get(6).is_none());
203 assert!(result.get(8).is_none());
204 assert_eq!(result.get(slots[0]).unwrap().len(), vec_check.len());
205 assert_eq!(result.get(slots[1]).unwrap().len(), vec_check.len());
206 }
207}