Properly handle the case where a new new allocation is cas'd
@@ -486,6 +486,7 @@ impl SegmentAccountant {
continue;
}
if let Some(segment_lsn) = segments[idx].lsn {
+ assert_ne!(segment_lsn, Lsn::max_value());
for (pid, lsn) in pids {
if lsn < segment_lsn {
// TODO is this avoidable? can punt more
@@ -515,9 +516,11 @@ impl SegmentAccountant {
// use last segment as active even if it's full
let io_buf_size = self.config.io_buf_size;
- let highest_lsn = segments.iter().fold(0, |acc, segment| {
- std::cmp::max(acc, segment.lsn.unwrap_or(acc))
- });
+ let highest_lsn = segments.iter()
+ .filter_map(|s| s.lsn)
+ .filter(|lsn| *lsn != Lsn::max_value())
+ .max()
+ .unwrap_or(0);
debug!(
"recovered highest_lsn in all segments: {}",
highest_lsn
@@ -816,6 +819,15 @@ impl SegmentAccountant {
);
for old_ptr in old_ptrs {
+ let old_lid = old_ptr.lid();
+
+ if old_lid == LogId::max_value() {
+ // this is used as a special value for initial
+ // Allocations before they are logged and
+ // fully installed with cas_page
+ continue;
+ }
+
if schedule_rm_blob && old_ptr.is_blob() {
trace!(
"queueing blob removal for {} in our own segment",
@@ -825,8 +837,6 @@ impl SegmentAccountant {
.remove_blob(old_ptr.blob().1, &self.config)?;
}
- let old_lid = old_ptr.lid();
-
let old_idx = self.lid_to_idx(old_lid);
if new_idx == old_idx {
// we probably haven't flushed this segment yet, so don't
@@ -1243,6 +1253,7 @@ impl SegmentAccountant {
}
fn lid_to_idx(&mut self, lid: LogId) -> usize {
+ assert_ne!(lid, LogId::max_value());
let idx = lid as usize / self.config.io_buf_size;
// TODO never resize like this, make it a single
