stacked_table: extract method that resolves head without releasing lock

GitBackend will reuse this lock to not assign multiple change ids to a
single commit. We could add a separate lock file that covers the section
from get_head() to save_table(), but I think reusing the table lock is good
enough.
This commit is contained in:
Yuya Nishihara 2023-05-19 17:47:29 +09:00
parent 3655da4f01
commit 83753e59f6

View file

@ -479,30 +479,36 @@ impl TableStore {
// head. Note that the locking isn't necessary for correctness; we
// take the lock only to avoid other concurrent processes from doing
// the same work (and producing another set of divergent heads).
let _lock = self.lock();
let mut tables = self.get_head_tables()?;
if tables.is_empty() {
let empty_table = MutableTable::full(self.key_size);
return self.save_table(empty_table);
}
if tables.len() == 1 {
// Return early so we don't write a table with no changes compared to its parent
return Ok(tables.pop().unwrap());
}
let mut merged_table = MutableTable::incremental(tables[0].clone());
for other in &tables[1..] {
merged_table.merge_in(other);
}
let merged_table = self.save_table(merged_table)?;
for table in &tables[1..] {
self.remove_head(table);
}
Ok(merged_table)
let (table, _) = self.get_head_locked()?;
Ok(table)
}
}
pub fn get_head_locked(&self) -> TableStoreResult<(Arc<ReadonlyTable>, FileLock)> {
let lock = self.lock();
let mut tables = self.get_head_tables()?;
if tables.is_empty() {
let empty_table = MutableTable::full(self.key_size);
let table = self.save_table(empty_table)?;
return Ok((table, lock));
}
if tables.len() == 1 {
// Return early so we don't write a table with no changes compared to its parent
return Ok((tables.pop().unwrap(), lock));
}
let mut merged_table = MutableTable::incremental(tables[0].clone());
for other in &tables[1..] {
merged_table.merge_in(other);
}
let merged_table = self.save_table(merged_table)?;
for table in &tables[1..] {
self.remove_head(table);
}
Ok((merged_table, lock))
}
}
#[cfg(test)]