in resctl-demo/src/report_ring.rs [226:296]
fn fill(&mut self, stride: u64, nr_slots: usize, src: &ReportRing) {
if stride != self.stride || nr_slots != self.nr_slots || self.src_cadence != src.cadence {
self.clear();
self.stride = stride;
self.nr_slots = nr_slots;
self.src_cadence = src.cadence;
self.step = stride * src.cadence;
}
if src.ring.len() == 0 {
debug!("empty ring");
return;
}
// we only need to scan enough to fill nr_slots, fast-forward next_src_at accordingly
let newest = src.ring.back().unwrap().at;
self.next_src_at = self
.next_src_at
.max(self.align(newest) - nr_slots as u64 * self.step);
// scan from back to determine how many records are new
let mut start = src.ring.len();
for i in (0..src.ring.len()).rev() {
if src.ring[i].at < self.next_src_at {
break;
}
start = i;
}
self.next_src_at = newest + self.src_cadence;
// process the new ones in chronological order
for i in start..src.ring.len() {
let rec = &src.ring[i];
let at = self.align(rec.at);
debug!(
"filling[{}] {:?} from {:?}",
i,
at as i64 - unix_now() as i64,
rec.at
);
if self.tip.at == 0 {
self.tip.at = at;
}
while self.tip.at < at {
let v = match self.tip.consume(self.step) {
Some((mut data, nr_samples)) => {
(self.aggr)(&mut data, nr_samples);
Some(data)
}
None => None,
};
self.data_ring.push_back(v);
}
(self.acc)(&mut self.tip.data, &(self.sel)(&rec.rep));
self.tip.nr_samples += 1;
if (rec.at % self.step) == (stride - 1) * self.src_cadence {
let v = match self.tip.consume(self.step) {
Some((mut data, nr_samples)) => {
(self.aggr)(&mut data, nr_samples);
Some(data)
}
None => None,
};
self.data_ring.push_back(v);
}
}
// truncate
while self.data_ring.len() > nr_slots {
self.data_ring.pop_front();
}
}