index: use local position in segment-local operations

I'm going to change the index format to store local positions in the lookup
table. That's not super important, but I think it makes sense because the
lookup table should never contain inter-segment links.

The mutable segment now stores local positions in its lookup map. The readonly
segment will be updated later.
This commit is contained in:
Yuya Nishihara 2023-12-21 18:09:52 +09:00
parent 3e43108abb
commit 1d11cffcfa
3 changed files with 22 additions and 11 deletions

View file

@ -44,7 +44,7 @@ pub(super) trait IndexSegment: Send + Sync {
fn name(&self) -> Option<String>;
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<IndexPosition>;
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<LocalPosition>;
/// Suppose the given `commit_id` exists, returns the previous and next
/// commit ids in lexicographical order.
@ -158,8 +158,10 @@ impl<'a> CompositeIndex<'a> {
}
pub fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<IndexPosition> {
self.ancestor_index_segments()
.find_map(|segment| segment.commit_id_to_pos(commit_id))
self.ancestor_index_segments().find_map(|segment| {
let LocalPosition(local_pos) = segment.commit_id_to_pos(commit_id)?;
Some(IndexPosition(local_pos + segment.num_parent_commits()))
})
}
/// Suppose the given `commit_id` exists, returns the previous and next

View file

@ -56,7 +56,7 @@ pub(super) struct MutableIndexSegment {
commit_id_length: usize,
change_id_length: usize,
graph: Vec<MutableGraphEntry>,
commit_lookup: BTreeMap<CommitId, IndexPosition>,
commit_lookup: BTreeMap<CommitId, LocalPosition>,
}
impl MutableIndexSegment {
@ -125,7 +125,7 @@ impl MutableIndexSegment {
}
self.commit_lookup.insert(
entry.commit_id.clone(),
IndexPosition(u32::try_from(self.graph.len()).unwrap() + self.num_parent_commits),
LocalPosition(u32::try_from(self.graph.len()).unwrap()),
);
self.graph.push(entry);
}
@ -222,9 +222,9 @@ impl MutableIndexSegment {
buf.extend_from_slice(entry.commit_id.as_bytes());
}
for (commit_id, pos) in &self.commit_lookup {
for (commit_id, LocalPosition(pos)) in &self.commit_lookup {
buf.extend_from_slice(commit_id.as_bytes());
buf.extend(pos.0.to_le_bytes());
buf.extend((pos + self.num_parent_commits).to_le_bytes());
}
buf[parent_overflow_offset..][..4]
@ -316,8 +316,8 @@ impl IndexSegment for MutableIndexSegment {
None
}
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<IndexPosition> {
self.commit_lookup.get(commit_id).cloned()
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<LocalPosition> {
self.commit_lookup.get(commit_id).copied()
}
fn resolve_neighbor_commit_ids(

View file

@ -122,6 +122,7 @@ impl CommitGraphEntry<'_> {
struct CommitLookupEntry<'a> {
data: &'a [u8],
commit_id_length: usize,
num_parent_commits: u32,
}
impl CommitLookupEntry<'_> {
@ -142,6 +143,13 @@ impl CommitLookupEntry<'_> {
let pos = u32::from_le_bytes(self.data[self.commit_id_length..][..4].try_into().unwrap());
IndexPosition(pos)
}
// TODO: better to store local pos in lookup table since there should be no
// inter-segment entry.
fn local_pos(&self) -> LocalPosition {
let IndexPosition(pos) = self.pos();
LocalPosition(pos - self.num_parent_commits)
}
}
/// Commit index segment backed by immutable file.
@ -336,6 +344,7 @@ impl ReadonlyIndexSegment {
CommitLookupEntry {
data: &self.data[offset..][..self.commit_lookup_entry_size],
commit_id_length: self.commit_id_length,
num_parent_commits: self.num_parent_commits,
}
}
@ -388,10 +397,10 @@ impl IndexSegment for ReadonlyIndexSegment {
Some(self.name.clone())
}
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<IndexPosition> {
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<LocalPosition> {
let lookup_pos = self.commit_id_byte_prefix_to_lookup_pos(commit_id)?;
let entry = self.commit_lookup_entry(lookup_pos);
(&entry.commit_id() == commit_id).then(|| entry.pos())
(&entry.commit_id() == commit_id).then(|| entry.local_pos())
}
fn resolve_neighbor_commit_ids(