11use crate :: { OpenSegment , Segment } ;
22use log:: warn;
3+ use std:: cmp:: max;
34#[ cfg( not( target_os = "windows" ) ) ]
45use std:: fs:: File ;
56use std:: io:: Error ;
@@ -60,7 +61,8 @@ impl SegmentCreatorV2 {
6061 /// The segment creator must be started before new segments will be created.
6162 pub fn new < P > (
6263 dir : P ,
63- mut existing : Vec < OpenSegment > ,
64+ open_segment : Option < & OpenSegment > ,
65+ mut unused_segments : Vec < OpenSegment > ,
6466 segment_capacity : usize ,
6567 segment_queue_len : usize ,
6668 ) -> SegmentCreatorV2
@@ -69,15 +71,20 @@ impl SegmentCreatorV2 {
6971 {
7072 let dir = dir. as_ref ( ) . to_path_buf ( ) ;
7173
72- existing . sort_by_key ( |segment| segment. id ) ;
74+ unused_segments . sort_by_key ( |segment| segment. id ) ;
7375
74- let current_id = existing. last ( ) . map_or ( 1 , |s| s. id + 1 ) ;
76+ // Find the current id by incrementing either last unused segment or open segment
77+ // If neither exists, start at 1
78+ let current_id = unused_segments
79+ . last ( )
80+ . or ( open_segment)
81+ . map_or ( 1 , |s| s. id + 1 ) ;
7582
7683 let mut result = Self {
7784 dir,
78- pending_segments : existing ,
85+ pending_segments : unused_segments ,
7986 segment_capacity,
80- segment_queue_len : segment_queue_len + 1 , // Always create at least one segment
87+ segment_queue_len : max ( segment_queue_len, 1 ) , // Always create at least one segment
8188 current_id,
8289 thread : None ,
8390 } ;
@@ -165,13 +172,19 @@ mod tests {
165172 init_logger ( ) ;
166173 let dir = Builder :: new ( ) . prefix ( "segment" ) . tempdir ( ) . unwrap ( ) ;
167174
168- let segments = vec ! [ OpenSegment {
175+ let segment = Some ( OpenSegment {
169176 id : 3 ,
170177 segment : Segment :: create ( dir. path ( ) . join ( "open-3" ) , 1024 ) . unwrap ( ) ,
178+ } ) ;
179+
180+ let unused_segments = vec ! [ OpenSegment {
181+ id: 4 ,
182+ segment: Segment :: create( dir. path( ) . join( "open-4" ) , 1024 ) . unwrap( ) ,
171183 } ] ;
172184
173- let mut creator = SegmentCreatorV2 :: new ( dir. path ( ) , segments, 1024 , 1 ) ;
174- for i in 3 ..10 {
185+ let mut creator =
186+ SegmentCreatorV2 :: new ( dir. path ( ) , segment. as_ref ( ) , unused_segments, 1024 , 1 ) ;
187+ for i in 4 ..10 {
175188 assert_eq ! ( i, creator. next( ) . unwrap( ) . id) ;
176189 }
177190
@@ -191,6 +204,45 @@ mod tests {
191204 eprintln ! ( "{:?}" , entry) ;
192205 }
193206
207+ assert_eq ! ( entries. len( ) , 10 - 3 + 1 ) ; // open-3 and open-4 existed, open-5 to open-9 created + open-10 created ahead
208+ }
209+
210+ #[ test]
211+ fn test_segment_creator_v2_no_unused ( ) {
212+ init_logger ( ) ;
213+ let dir = Builder :: new ( ) . prefix ( "segment" ) . tempdir ( ) . unwrap ( ) ;
214+
215+ let segment = Some ( OpenSegment {
216+ id : 3 ,
217+ segment : Segment :: create ( dir. path ( ) . join ( "open-3" ) , 1024 ) . unwrap ( ) ,
218+ } ) ;
219+
220+ let unused_segments = vec ! [ ] ;
221+
222+ let mut creator =
223+ SegmentCreatorV2 :: new ( dir. path ( ) , segment. as_ref ( ) , unused_segments, 1024 , 1 ) ;
224+ for i in 4 ..10 {
225+ let another_segment = creator. next ( ) . unwrap ( ) ;
226+ eprintln ! ( "another_segment = {:#?}" , another_segment) ;
227+ assert_eq ! ( i, another_segment. id) ;
228+ }
229+
230+ // This awaits for the thread to finish
231+ drop ( creator) ;
232+
233+ // List directory contents
234+ let mut entries: Vec < _ > = std:: fs:: read_dir ( dir. path ( ) )
235+ . unwrap ( )
236+ . map ( |res| res. map ( |e| e. file_name ( ) ) )
237+ . collect :: < Result < _ , std:: io:: Error > > ( )
238+ . unwrap ( ) ;
239+
240+ entries. sort ( ) ;
241+
242+ for entry in & entries {
243+ eprintln ! ( "{:?}" , entry) ;
244+ }
245+
194246 assert_eq ! ( entries. len( ) , 10 - 3 + 1 ) ; // open-3 existed, open-4 to open-9 created + open-10 created ahead
195247 }
196248}
0 commit comments