@@ -91,7 +91,15 @@ fn merge(
91
91
index : & Index ,
92
92
mut segment_entries : Vec < SegmentEntry > ,
93
93
target_opstamp : Opstamp ,
94
- ) -> crate :: Result < SegmentEntry > {
94
+ ) -> crate :: Result < Option < SegmentEntry > > {
95
+ let num_docs = segment_entries
96
+ . iter ( )
97
+ . map ( |segment| segment. meta ( ) . num_docs ( ) as u64 )
98
+ . sum :: < u64 > ( ) ;
99
+ if num_docs == 0 {
100
+ return Ok ( None ) ;
101
+ }
102
+
95
103
// first we need to apply deletes to our segment.
96
104
let merged_segment = index. new_segment ( ) ;
97
105
@@ -120,7 +128,7 @@ fn merge(
120
128
let merged_segment_id = merged_segment. id ( ) ;
121
129
122
130
let segment_meta = index. new_segment_meta ( merged_segment_id, num_docs) ;
123
- Ok ( SegmentEntry :: new ( segment_meta, delete_cursor, None ) )
131
+ Ok ( Some ( SegmentEntry :: new ( segment_meta, delete_cursor, None ) ) )
124
132
}
125
133
126
134
/// Advanced: Merges a list of segments from different indices in a new index.
@@ -475,7 +483,10 @@ impl SegmentUpdater {
475
483
// suggested and the moment when it ended up being executed.)
476
484
//
477
485
// `segment_ids` is required to be non-empty.
478
- pub fn start_merge ( & self , merge_operation : MergeOperation ) -> FutureResult < SegmentMeta > {
486
+ pub fn start_merge (
487
+ & self ,
488
+ merge_operation : MergeOperation ,
489
+ ) -> FutureResult < Option < SegmentMeta > > {
479
490
assert ! (
480
491
!merge_operation. segment_ids( ) . is_empty( ) ,
481
492
"Segment_ids cannot be empty."
@@ -512,18 +523,19 @@ impl SegmentUpdater {
512
523
merge_operation. target_opstamp ( ) ,
513
524
) {
514
525
Ok ( after_merge_segment_entry) => {
515
- let segment_meta_res =
516
- segment_updater. end_merge ( merge_operation, after_merge_segment_entry) ;
517
- let _send_result = merging_future_send. send ( segment_meta_res) ;
526
+ let res = segment_updater. end_merge ( merge_operation, after_merge_segment_entry) ;
527
+ let _send_result = merging_future_send. send ( res) ;
518
528
}
519
529
Err ( merge_error) => {
520
530
warn ! (
521
531
"Merge of {:?} was cancelled: {:?}" ,
522
532
merge_operation. segment_ids( ) . to_vec( ) ,
523
533
merge_error
524
534
) ;
535
+ if cfg ! ( test) {
536
+ panic ! ( "{:?}" , merge_error) ;
537
+ }
525
538
let _send_result = merging_future_send. send ( Err ( merge_error) ) ;
526
- assert ! ( !cfg!( test) , "Merge failed." ) ;
527
539
}
528
540
}
529
541
} ) ;
@@ -573,35 +585,42 @@ impl SegmentUpdater {
573
585
fn end_merge (
574
586
& self ,
575
587
merge_operation : MergeOperation ,
576
- mut after_merge_segment_entry : SegmentEntry ,
577
- ) -> crate :: Result < SegmentMeta > {
588
+ mut after_merge_segment_entry : Option < SegmentEntry > ,
589
+ ) -> crate :: Result < Option < SegmentMeta > > {
578
590
let segment_updater = self . clone ( ) ;
579
- let after_merge_segment_meta = after_merge_segment_entry. meta ( ) . clone ( ) ;
591
+ let after_merge_segment_meta = after_merge_segment_entry
592
+ . as_ref ( )
593
+ . map ( |after_merge_segment_entry| after_merge_segment_entry. meta ( ) . clone ( ) ) ;
580
594
self . schedule_task ( move || {
581
- info ! ( "End merge {:?}" , after_merge_segment_entry. meta( ) ) ;
595
+ info ! (
596
+ "End merge {:?}" ,
597
+ after_merge_segment_entry. as_ref( ) . map( |entry| entry. meta( ) )
598
+ ) ;
582
599
{
583
- let mut delete_cursor = after_merge_segment_entry. delete_cursor ( ) . clone ( ) ;
584
- if let Some ( delete_operation) = delete_cursor. get ( ) {
585
- let committed_opstamp = segment_updater. load_meta ( ) . opstamp ;
586
- if delete_operation. opstamp < committed_opstamp {
587
- let index = & segment_updater. index ;
588
- let segment = index. segment ( after_merge_segment_entry. meta ( ) . clone ( ) ) ;
589
- if let Err ( advance_deletes_err) = advance_deletes (
590
- segment,
591
- & mut after_merge_segment_entry,
592
- committed_opstamp,
593
- ) {
594
- error ! (
595
- "Merge of {:?} was cancelled (advancing deletes failed): {:?}" ,
596
- merge_operation. segment_ids( ) ,
597
- advance_deletes_err
598
- ) ;
599
- assert ! ( !cfg!( test) , "Merge failed." ) ;
600
-
601
- // ... cancel merge
602
- // `merge_operations` are tracked. As it is dropped, the
603
- // the segment_ids will be available again for merge.
604
- return Err ( advance_deletes_err) ;
600
+ if let Some ( after_merge_segment_entry) = after_merge_segment_entry. as_mut ( ) {
601
+ let mut delete_cursor = after_merge_segment_entry. delete_cursor ( ) . clone ( ) ;
602
+ if let Some ( delete_operation) = delete_cursor. get ( ) {
603
+ let committed_opstamp = segment_updater. load_meta ( ) . opstamp ;
604
+ if delete_operation. opstamp < committed_opstamp {
605
+ let index = & segment_updater. index ;
606
+ let segment = index. segment ( after_merge_segment_entry. meta ( ) . clone ( ) ) ;
607
+ if let Err ( advance_deletes_err) = advance_deletes (
608
+ segment,
609
+ after_merge_segment_entry,
610
+ committed_opstamp,
611
+ ) {
612
+ error ! (
613
+ "Merge of {:?} was cancelled (advancing deletes failed): {:?}" ,
614
+ merge_operation. segment_ids( ) ,
615
+ advance_deletes_err
616
+ ) ;
617
+ assert ! ( !cfg!( test) , "Merge failed." ) ;
618
+
619
+ // ... cancel merge
620
+ // `merge_operations` are tracked. As it is dropped, the
621
+ // the segment_ids will be available again for merge.
622
+ return Err ( advance_deletes_err) ;
623
+ }
605
624
}
606
625
}
607
626
}
0 commit comments