mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
dag: make children work with missing high-level segments
Summary: This makes the algorithm a bit more robust. Now none of the DAG algorithms depend on high-level segments are complete and cover all low-level segments. This also removes constraints. For example, SyncableIdDag can now just deref() to the normal IdDag for queries without worrying about correctness. Reviewed By: sfilipco Differential Revision: D24399503 fbshipit-source-id: e6a91010cff82264cf423e2f24dee1d372822ef6
This commit is contained in:
parent
f290afe421
commit
496724e45e
@ -54,8 +54,6 @@ pub struct IdDag<Store> {
|
|||||||
/// - The in-memory high-level segments are not lagging, but might be
|
/// - The in-memory high-level segments are not lagging, but might be
|
||||||
/// fragmented because the last segment per level might not cover
|
/// fragmented because the last segment per level might not cover
|
||||||
/// as many lower-level segments as it can.
|
/// as many lower-level segments as it can.
|
||||||
/// Some DAG algorithms (children_set)
|
|
||||||
/// assume high-level segments are not lagging.
|
|
||||||
/// - The on-disk data has lagging high-level segment. This is helpful
|
/// - The on-disk data has lagging high-level segment. This is helpful
|
||||||
/// because the Index backend is not good at (cheaply) deleting data
|
/// because the Index backend is not good at (cheaply) deleting data
|
||||||
/// with bytes freed.
|
/// with bytes freed.
|
||||||
@ -65,8 +63,6 @@ pub struct IdDag<Store> {
|
|||||||
/// - SyncableIdDag -> IdDag needs to re-add the high-level segments.
|
/// - SyncableIdDag -> IdDag needs to re-add the high-level segments.
|
||||||
/// This is done by calling `build_all_high_level_segments()` at
|
/// This is done by calling `build_all_high_level_segments()` at
|
||||||
/// `SyncableIdDag::sync()`.
|
/// `SyncableIdDag::sync()`.
|
||||||
///
|
|
||||||
/// (Consider making `children_set` not rely on the property)
|
|
||||||
pub struct SyncableIdDag<'a, Store: GetLock> {
|
pub struct SyncableIdDag<'a, Store: GetLock> {
|
||||||
dag: &'a mut IdDag<Store>,
|
dag: &'a mut IdDag<Store>,
|
||||||
lock: <Store as GetLock>::LockT,
|
lock: <Store as GetLock>::LockT,
|
||||||
@ -892,12 +888,27 @@ impl<Store: IdDagStore> IdDag<Store> {
|
|||||||
|
|
||||||
fn visit_segments<S: IdDagStore>(
|
fn visit_segments<S: IdDagStore>(
|
||||||
ctx: &mut Context<S>,
|
ctx: &mut Context<S>,
|
||||||
range: Span,
|
mut range: Span,
|
||||||
level: Level,
|
level: Level,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for seg in ctx.this.iter_segments_descending(range.high, level)? {
|
for seg in ctx.this.iter_segments_descending(range.high, level)? {
|
||||||
let seg = seg?;
|
let seg = seg?;
|
||||||
let span = seg.span()?;
|
let span = seg.span()?;
|
||||||
|
// `range` is all valid. If a high-level segment misses it, try
|
||||||
|
// a lower level one.
|
||||||
|
if span.high < range.high {
|
||||||
|
let missing_range = Span::from((span.high + 1)..=range.high);
|
||||||
|
if level > 0 {
|
||||||
|
visit_segments(ctx, missing_range, level - 1)?;
|
||||||
|
} else {
|
||||||
|
return bug(format!(
|
||||||
|
"flat segments should have covered: {:?} returned by all()",
|
||||||
|
missing_range
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
range.high = span.low.max(Id(1)) - 1;
|
||||||
|
|
||||||
if span.low < range.low || span.high < ctx.result_lower_bound {
|
if span.low < range.low || span.high < ctx.result_lower_bound {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -969,7 +980,9 @@ impl<Store: IdDagStore> IdDag<Store> {
|
|||||||
result: SpanSet::empty(),
|
result: SpanSet::empty(),
|
||||||
};
|
};
|
||||||
|
|
||||||
visit_segments(&mut ctx, (Id::MIN..=Id::MAX).into(), self.max_level)?;
|
for span in self.all()?.as_spans() {
|
||||||
|
visit_segments(&mut ctx, *span, self.max_level)?;
|
||||||
|
}
|
||||||
|
|
||||||
if !tracing_span.is_disabled() {
|
if !tracing_span.is_disabled() {
|
||||||
tracing_span.record("result", &field::debug(&ctx.result));
|
tracing_span.record("result", &field::debug(&ctx.result));
|
||||||
|
Loading…
Reference in New Issue
Block a user