@@ -267,69 +267,70 @@ impl Manifest {
267
267
writer : & str ,
268
268
) -> Option < Snapshot > {
269
269
let writer = writer. to_string ( ) ;
270
- let can_snapshot_snapshots = self . snapshots . iter ( ) . filter ( |s| s. depth < 2 ) . count ( )
271
- >= snapshot_options. snapshot_rollover_threshold ;
272
- let can_snapshot_fragments =
273
- self . fragments . len ( ) >= snapshot_options. fragment_rollover_threshold ;
274
- if can_snapshot_snapshots || can_snapshot_fragments {
270
+ let mut snapshot_depth = self . snapshots . iter ( ) . map ( |s| s. depth ) . max ( ) . unwrap_or ( 0 ) ;
271
+ while snapshot_depth > 0 {
275
272
// NOTE(rescrv): We _either_ compact a snapshot of snapshots or a snapshot of log
276
273
// fragments. We don't do both as interior snapshot nodes only refer to objects of the
277
274
// same type. Manifests are the only objects to refer to both fragments and snapshots.
278
275
let mut snapshots = vec ! [ ] ;
279
- let mut fragments = vec ! [ ] ;
280
276
let mut setsum = Setsum :: default ( ) ;
281
- let depth = if can_snapshot_snapshots {
282
- for snapshot in self . snapshots . iter ( ) {
283
- if snapshot. depth < 2
284
- && snapshots. len ( ) < snapshot_options. snapshot_rollover_threshold
285
- {
286
- setsum += snapshot. setsum ;
287
- snapshots. push ( snapshot. clone ( ) ) ;
288
- }
277
+ for snapshot in self . snapshots . iter ( ) . filter ( |s| s. depth == snapshot_depth) {
278
+ if snapshots. len ( ) < snapshot_options. snapshot_rollover_threshold {
279
+ setsum += snapshot. setsum ;
280
+ snapshots. push ( snapshot. clone ( ) ) ;
289
281
}
290
- 2
291
- } else if can_snapshot_fragments {
292
- for fragment in self . fragments . iter ( ) {
293
- // NOTE(rescrv): When taking a snapshot, it's important that we keep around
294
- // one fragment so that the max seq no is always calculable.
295
- //
296
- // Otherwise, a low-traffic log could be compacted into a state where all of
297
- // its fragments have been compacted and therefore the implicit fragment seq no
298
- // for each fragment is zero. This wedges the manifest manager.
299
- //
300
- // The fix is to keep around the last fragment.
301
- if fragments. len ( ) < snapshot_options. fragment_rollover_threshold
302
- && self
303
- . fragments
304
- . iter ( )
305
- . map ( |f| f. seq_no )
306
- . max ( )
307
- . unwrap_or ( FragmentSeqNo ( 0 ) )
308
- != fragment. seq_no
309
- {
310
- setsum += fragment. setsum ;
311
- fragments. push ( fragment. clone ( ) ) ;
312
- }
282
+ }
283
+ if snapshots. len ( ) >= snapshot_options. snapshot_rollover_threshold {
284
+ let path = unprefixed_snapshot_path ( setsum) ;
285
+ return Some ( Snapshot {
286
+ path,
287
+ depth : snapshot_depth + 1 ,
288
+ setsum,
289
+ writer,
290
+ snapshots,
291
+ fragments : vec ! [ ] ,
292
+ } ) ;
293
+ }
294
+ snapshot_depth -= 1 ;
295
+ }
296
+ if self . fragments . len ( ) >= snapshot_options. fragment_rollover_threshold {
297
+ let mut setsum = Setsum :: default ( ) ;
298
+ let mut fragments = vec ! [ ] ;
299
+ for fragment in self . fragments . iter ( ) {
300
+ // NOTE(rescrv): When taking a snapshot, it's important that we keep around
301
+ // one fragment so that the max seq no is always calculable.
302
+ //
303
+ // Otherwise, a low-traffic log could be compacted into a state where all of
304
+ // its fragments have been compacted and therefore the implicit fragment seq no
305
+ // for each fragment is zero. This wedges the manifest manager.
306
+ //
307
+ // The fix is to keep around the last fragment.
308
+ if fragments. len ( ) < snapshot_options. fragment_rollover_threshold
309
+ && self
310
+ . fragments
311
+ . iter ( )
312
+ . map ( |f| f. seq_no )
313
+ . max ( )
314
+ . unwrap_or ( FragmentSeqNo ( 0 ) )
315
+ != fragment. seq_no
316
+ {
317
+ setsum += fragment. setsum ;
318
+ fragments. push ( fragment. clone ( ) ) ;
313
319
}
314
- 1
315
- } else {
316
- unreachable ! ( "I checked A || B above, then checked A and B separately; should not reach here." ) ;
317
- } ;
318
- if snapshots. is_empty ( ) && fragments. is_empty ( ) {
319
- return None ;
320
320
}
321
- let path = unprefixed_snapshot_path ( setsum ) ;
322
- Some ( Snapshot {
323
- path ,
324
- depth ,
325
- setsum ,
326
- writer ,
327
- snapshots ,
328
- fragments ,
329
- } )
330
- } else {
331
- None
321
+ if fragments . len ( ) >= snapshot_options . fragment_rollover_threshold {
322
+ let path = unprefixed_snapshot_path ( setsum ) ;
323
+ return Some ( Snapshot {
324
+ path ,
325
+ depth : 1 ,
326
+ setsum ,
327
+ writer ,
328
+ snapshots : vec ! [ ] ,
329
+ fragments ,
330
+ } ) ;
331
+ }
332
332
}
333
+ None
333
334
}
334
335
335
336
/// Given a snapshot, apply it to the manifest. This modifies the manifest to refer to the
0 commit comments