Skip to content

Commit eeeffdc

Browse files
committed
refactor: segment point read
1 parent ab04f21 commit eeeffdc

File tree

1 file changed

+75
-88
lines changed

1 file changed

+75
-88
lines changed

src/segment/mod.rs

Lines changed: 75 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -116,108 +116,95 @@ impl Segment {
116116
}
117117
}
118118

119+
// Get the block handle, if it doesn't exist, the key is definitely not found
120+
let Some(block_handle) = self.block_index.get_latest(key.as_ref())? else {
121+
return Ok(None);
122+
};
123+
124+
// The block should definitely exist, we just got the block handle before
125+
let Some(block) = load_and_cache_by_block_handle(
126+
&self.descriptor_table,
127+
&self.block_cache,
128+
&self.metadata.id,
129+
&block_handle,
130+
)?
131+
else {
132+
return Ok(None);
133+
};
134+
135+
let mut maybe_our_items_iter = block
136+
.items
137+
.iter()
138+
// TODO: maybe binary search can be used, but it needs to find the max seqno
139+
.filter(|item| item.key == key.as_ref().into());
140+
119141
match seqno {
120142
None => {
121143
// NOTE: Fastpath for non-seqno reads (which are most common)
122144
// This avoids setting up a rather expensive block iterator
123145
// (see explanation for that below)
124146
// This only really works because sequence numbers are sorted
125147
// in descending order
148+
//
149+
// If it doesn't exist, we avoid loading the next block
150+
// because the block handle was retrieved using the item key, so if
151+
// the item exists, it HAS to be in the first block
126152

127-
if let Some(block_handle) = self.block_index.get_latest(key.as_ref())? {
128-
let block = load_and_cache_by_block_handle(
129-
&self.descriptor_table,
130-
&self.block_cache,
131-
&self.metadata.id,
132-
&block_handle,
133-
)?;
134-
135-
let item = block.map_or_else(
136-
|| Ok(None),
137-
|block| {
138-
// TODO: maybe binary search can be used, but it needs to find the max seqno
139-
Ok(block
140-
.items
141-
.iter()
142-
.find(|item| item.key == key.as_ref().into())
143-
.cloned())
144-
},
145-
);
146-
147-
item
148-
} else {
149-
Ok(None)
150-
}
153+
Ok(maybe_our_items_iter.next().cloned())
151154
}
152155
Some(seqno) => {
153-
// NOTE: if block does not contain entry, fallback to prefix as seen below
154-
if let Some(block_handle) = self.block_index.get_latest(key.as_ref())? {
155-
let block = load_and_cache_by_block_handle(
156-
&self.descriptor_table,
157-
&self.block_cache,
158-
&self.metadata.id,
159-
&block_handle,
160-
)?;
161-
162-
if let Some(block) = block {
163-
for item in block
164-
.items
165-
.iter()
166-
// TODO: maybe binary search can be used, but it needs to find the max seqno
167-
.filter(|item| item.key == key.as_ref().into())
168-
{
169-
if item.seqno < seqno {
170-
return Ok(Some(item.clone()));
171-
}
172-
}
156+
for item in maybe_our_items_iter {
157+
if item.seqno < seqno {
158+
return Ok(Some(item.clone()));
173159
}
160+
}
174161

175-
// NOTE: For finding a specific seqno,
176-
// we need to use a prefixed reader
177-
// because nothing really prevents the version
178-
// we are searching for to be in the next block
179-
// after the one our key starts in
180-
//
181-
// Example (key:seqno), searching for a:2:
182-
//
183-
// [..., a:5, a:4] [a:3, a:2, b: 4, b:3]
184-
// ^ ^
185-
// Block A Block B
186-
//
187-
// Based on get_lower_bound_block, "a" is in Block A
188-
// However, we are searching for A with seqno 2, which
189-
// unfortunately is in the next block
190-
191-
let Some(next_block_handle) = self
192-
.block_index
193-
.get_next_block_key(&block_handle.start_key)?
194-
else {
162+
// NOTE: If we got here, the item was not in the block :(
163+
164+
// NOTE: For finding a specific seqno,
165+
// we need to use a prefixed reader
166+
// because nothing really prevents the version
167+
// we are searching for to be in the next block
168+
// after the one our key starts in
169+
//
170+
// Example (key:seqno), searching for a:2:
171+
//
172+
// [..., a:5, a:4] [a:3, a:2, b: 4, b:3]
173+
// ^ ^
174+
// Block A Block B
175+
//
176+
// Based on get_lower_bound_block, "a" is in Block A
177+
// However, we are searching for A with seqno 2, which
178+
// unfortunately is in the next block
179+
180+
// Load next block and setup block iterator
181+
let Some(next_block_handle) = self
182+
.block_index
183+
.get_next_block_key(&block_handle.start_key)?
184+
else {
185+
return Ok(None);
186+
};
187+
188+
let iter = Reader::new(
189+
Arc::clone(&self.descriptor_table),
190+
self.metadata.id.clone(),
191+
Some(Arc::clone(&self.block_cache)),
192+
Arc::clone(&self.block_index),
193+
Some(&next_block_handle.start_key),
194+
None,
195+
);
196+
197+
for item in iter {
198+
let item = item?;
199+
200+
// Just stop iterating once we go past our desired key
201+
if &*item.key != key {
195202
return Ok(None);
196-
};
197-
198-
let iter = Reader::new(
199-
Arc::clone(&self.descriptor_table),
200-
self.metadata.id.clone(),
201-
Some(Arc::clone(&self.block_cache)),
202-
Arc::clone(&self.block_index),
203-
Some(&next_block_handle.start_key),
204-
None,
205-
);
206-
207-
for item in iter {
208-
let item = item?;
209-
210-
// Just stop iterating once we go past our desired key
211-
if &*item.key != key {
212-
return Ok(None);
213-
}
214-
215-
if item.seqno < seqno {
216-
return Ok(Some(item));
217-
}
218203
}
219-
} else {
220-
return Ok(None);
204+
205+
if item.seqno < seqno {
206+
return Ok(Some(item));
207+
}
221208
}
222209

223210
Ok(None)

0 commit comments

Comments
 (0)