1212 append /4 ,
1313 sync /1 ,
1414 fold /6 ,
15+ is_modified /1 ,
1516 read_sparse /4 ,
1617 term_query /2 ,
1718 close /1 ,
2728
2829-include (" ra.hrl" ).
2930
31+ -include_lib (" kernel/include/file.hrl" ).
32+
3033-define (VERSION , 2 ).
3134-define (MAGIC , " RASG" ).
3235-define (HEADER_SIZE , 4 + (16 div 8 ) + (16 div 8 )).
@@ -112,6 +115,7 @@ open(Filename, Options) ->
112115 end .
113116
114117process_file (true , Mode , Filename , Fd , Options ) ->
118+ AccessPattern = maps :get (access_pattern , Options , random ),
115119 case read_header (Fd ) of
116120 {ok , Version , MaxCount } ->
117121 MaxPending = maps :get (max_pending , Options , ? SEGMENT_MAX_PENDING ),
@@ -120,7 +124,6 @@ process_file(true, Mode, Filename, Fd, Options) ->
120124 {NumIndexRecords , DataOffset , Range , Index } =
121125 recover_index (Fd , Version , MaxCount ),
122126 IndexOffset = ? HEADER_SIZE + NumIndexRecords * IndexRecordSize ,
123- AccessPattern = maps :get (access_pattern , Options , random ),
124127 Mode = maps :get (mode , Options , append ),
125128 ComputeChecksums = maps :get (compute_checksums , Options , true ),
126129 {ok , # state {cfg = # cfg {version = Version ,
@@ -184,16 +187,15 @@ append(#state{cfg = #cfg{max_pending = PendingCount},
184187append (# state {cfg = # cfg {version = Version ,
185188 mode = append } = Cfg ,
186189 index_offset = IndexOffset ,
187- data_start = DataStart ,
188190 data_offset = DataOffset ,
189191 range = Range0 ,
190192 pending_count = PendCnt ,
191193 pending_index = IdxPend0 ,
192194 pending_data = DataPend0 } = State ,
193195 Index , Term , {Length , Data }) ->
194- % check if file is full
195- case IndexOffset < DataStart of
196- true ->
196+
197+ case is_full ( State ) of
198+ false ->
197199 % TODO: check length is less than #FFFFFFFF ??
198200 Checksum = compute_checksum (Cfg , Data ),
199201 OSize = offset_size (Version ),
@@ -209,7 +211,7 @@ append(#state{cfg = #cfg{version = Version,
209211 pending_data = [DataPend0 , Data ],
210212 pending_count = PendCnt + 1 }
211213 };
212- false ->
214+ true ->
213215 {error , full }
214216 end ;
215217append (State , Index , Term , Data )
@@ -271,38 +273,58 @@ fold(#state{cfg = #cfg{mode = read} = Cfg,
271273 FromIdx , ToIdx , Fun , AccFun , Acc ) ->
272274 fold0 (Cfg , Cache , FromIdx , ToIdx , Index , Fun , AccFun , Acc ).
273275
276+ -spec is_modified (state ()) -> boolean ().
277+ is_modified (# state {cfg = # cfg {fd = Fd },
278+ data_offset = DataOffset } = State ) ->
279+ case is_full (State ) of
280+ true ->
281+ % % a full segment cannot be appended to.
282+ false ;
283+ false ->
284+ % % get info and compare to data_offset
285+ {ok , # file_info {size = Size }} = prim_file :read_handle_info (Fd ),
286+ Size > DataOffset
287+ end .
288+
274289-spec read_sparse (state (), [ra_index ()],
275290 fun ((ra :index (), ra_term (), binary (), Acc ) -> Acc ),
276291 Acc ) ->
277- {NumRead :: non_neg_integer (), Acc }
292+ {ok , NumRead :: non_neg_integer (), Acc } | { error , modified }
278293 when Acc :: term ().
279294read_sparse (# state {index = Index ,
280- cfg = Cfg }, Indexes , AccFun , Acc ) ->
281- Cache0 = prepare_cache (Cfg , Indexes , Index ),
282- read_sparse0 (Cfg , Indexes , Index , Cache0 , Acc , AccFun , 0 ).
295+ cfg = # cfg {fd = Fd }} = State ,
296+ Indexes , AccFun , Acc ) ->
297+ case is_modified (State ) of
298+ true ->
299+ {error , modified };
300+ false ->
301+ Cache0 = prepare_cache (Fd , Indexes , Index ),
302+ read_sparse0 (Fd , Indexes , Index , Cache0 , Acc , AccFun , 0 )
303+ end .
283304
284- read_sparse0 (_Cfg , [], _Index , _Cache , Acc , _AccFun , Num ) ->
285- {Num , Acc };
286- read_sparse0 (Cfg , [NextIdx | Rem ] = Indexes , Index , Cache0 , Acc , AccFun , Num )
305+ read_sparse0 (_Fd , [], _Index , _Cache , Acc , _AccFun , Num ) ->
306+ {ok , Num , Acc };
307+ read_sparse0 (Fd , [NextIdx | Rem ] = Indexes , Index , Cache0 , Acc , AccFun , Num )
287308 when is_map_key (NextIdx , Index ) ->
288- {Term , Offset , Length , _ } = map_get (NextIdx , Index ),
289- case cache_read (Cache0 , Offset , Length ) of
309+ {Term , Pos , Length , _ } = map_get (NextIdx , Index ),
310+ case cache_read (Cache0 , Pos , Length ) of
290311 false ->
291- case prepare_cache (Cfg , Indexes , Index ) of
312+ case prepare_cache (Fd , Indexes , Index ) of
292313 undefined ->
293- {ok , Data , _ } = pread (Cfg , undefined , Offset , Length ),
294- read_sparse0 (Cfg , Rem , Index , undefined ,
314+ % % TODO: check for partial data?
315+ {ok , Data } = file :pread (Fd , Pos , Length ),
316+ read_sparse0 (Fd , Rem , Index , undefined ,
295317 AccFun (NextIdx , Term , Data , Acc ),
296318 AccFun , Num + 1 );
297319 Cache ->
298- read_sparse0 (Cfg , Indexes , Index , Cache ,
299- Acc , AccFun , Num + 1 )
320+ read_sparse0 (Fd , Indexes , Index , Cache ,
321+ Acc , AccFun , Num )
300322 end ;
301323 Data ->
302- read_sparse0 (Cfg , Rem , Index , Cache0 ,
324+ read_sparse0 (Fd , Rem , Index , Cache0 ,
303325 AccFun (NextIdx , Term , Data , Acc ), AccFun , Num + 1 )
304326 end ;
305- read_sparse0 (_Cfg , [NextIdx | _ ], _Index , _Cache , _Acc , _AccFun , _Num ) ->
327+ read_sparse0 (_Fd , [NextIdx | _ ], _Index , _Cache , _Acc , _AccFun , _Num ) ->
306328 exit ({missing_key , NextIdx }).
307329
308330cache_read ({CPos , CLen , Bin }, Pos , Length )
@@ -313,9 +335,9 @@ cache_read({CPos, CLen, Bin}, Pos, Length)
313335cache_read (_ , _ , _ ) ->
314336 false .
315337
316- prepare_cache (# cfg {} = _Cfg , [_ ], _SegIndex ) ->
338+ prepare_cache (_Fd , [_ ], _SegIndex ) ->
317339 undefined ;
318- prepare_cache (# cfg { fd = Fd } = _Cfg , [FirstIdx | Rem ], SegIndex ) ->
340+ prepare_cache (Fd , [FirstIdx | Rem ], SegIndex ) ->
319341 case consec_run (FirstIdx , FirstIdx , Rem ) of
320342 {Idx , Idx } ->
321343 % % no run, no cache;
@@ -622,6 +644,10 @@ validate_checksum(0, _) ->
622644validate_checksum (Crc , Data ) ->
623645 Crc == erlang :crc32 (Data ).
624646
647+ is_full (# state {index_offset = IndexOffset ,
648+ data_start = DataStart }) ->
649+ IndexOffset >= DataStart .
650+
625651-ifdef (TEST ).
626652-include_lib (" eunit/include/eunit.hrl" ).
627653
0 commit comments