11-module (rabbit_log_tail ).
22
33-export ([tail_n_lines /2 ]).
4- -export ([init_tail_stream /3 ]).
4+ -export ([init_tail_stream /4 ]).
55
66-define (GUESS_OFFSET , 200 ).
77
8- init_tail_stream (Filename , Pid , Ref ) ->
8+ init_tail_stream (Filename , Pid , Ref , Duration ) ->
99 RPCProc = self (),
1010 Reader = spawn (fun () ->
1111 link (Pid ),
1212 case file :open (Filename , [read , binary ]) of
1313 {ok , File } ->
14+ TimeLimit = case Duration of
15+ infinity -> infinity ;
16+ _ -> erlang :system_time (second ) + Duration
17+ end ,
1418 {ok , _ } = file :position (File , eof ),
1519 RPCProc ! {Ref , opened },
16- read_loop (File , Pid , Ref );
20+ read_loop (File , Pid , Ref , TimeLimit );
1721 {error , _ } = Err ->
1822 RPCProc ! {Ref , Err }
1923 end
@@ -26,16 +30,20 @@ init_tail_stream(Filename, Pid, Ref) ->
2630 {error , timeout }
2731 end .
2832
29- read_loop (File , Pid , Ref ) ->
30- case file :read (File , ? GUESS_OFFSET ) of
31- {ok , Data } ->
32- Pid ! {Ref , Data , confinue },
33- read_loop (File , Pid , Ref );
34- eof ->
35- timer :sleep (1000 ),
36- read_loop (File , Pid , Ref );
37- {error , _ } = Err ->
38- Pid ! {Ref , Err , finished }
33+ read_loop (File , Pid , Ref , TimeLimit ) ->
34+ case is_integer (TimeLimit ) andalso erlang :system_time (second ) > TimeLimit of
35+ true -> Pid ! {Ref , <<>>, finished };
36+ false ->
37+ case file :read (File , ? GUESS_OFFSET ) of
38+ {ok , Data } ->
39+ Pid ! {Ref , Data , confinue },
40+ read_loop (File , Pid , Ref , TimeLimit );
41+ eof ->
42+ timer :sleep (1000 ),
43+ read_loop (File , Pid , Ref , TimeLimit );
44+ {error , _ } = Err ->
45+ Pid ! {Ref , Err , finished }
46+ end
3947 end .
4048
4149tail_n_lines (Filename , N ) ->
@@ -46,7 +54,7 @@ tail_n_lines(Filename, N) ->
4654 Result = reverse_read_n_lines (N , N , File , Eof , Eof ),
4755 file :close (File ),
4856 Result ;
49- Error -> Error
57+ { error , _ } = Error -> Error
5058 end .
5159
5260reverse_read_n_lines (N , OffsetN , File , Position , Eof ) ->
@@ -63,23 +71,24 @@ reverse_read_n_lines(N, OffsetN, File, Position, Eof) ->
6371 _ ->
6472 reverse_read_n_lines (N , N - NLines + 1 , File , GuessPosition , Eof )
6573 end ;
66- Error -> Error
74+ { error , _ } = Error -> Error
6775 end .
6876
6977read_from_position (File , GuessPosition , Eof ) ->
7078 file :pread (File , GuessPosition , max (0 , Eof - GuessPosition )).
7179
7280read_lines_from_position (File , GuessPosition , Eof ) ->
7381 case read_from_position (File , GuessPosition , Eof ) of
74- {ok , Data } -> {ok , crop_lines (Data )};
75- Error -> Error
76- end .
77-
78- crop_lines (Data ) ->
79- % % Drop the first line, because it's most likely partial.
80- case binary :split (Data , <<" \n " >>, [global , trim ]) of
81- [_ |Rest ] -> Rest ;
82- [] -> []
82+ {ok , Data } ->
83+ Lines = binary :split (Data , <<" \n " >>, [global , trim ]),
84+ case {GuessPosition , Lines } of
85+ % % If position is 0 - there are no partial lines
86+ {0 , _ } -> {ok , Lines };
87+ % % Remove first line as it can be partial
88+ {_ , [_ | Rest ]} -> {ok , Rest };
89+ {_ , []} -> {ok , []}
90+ end ;
91+ {error , _ } = Error -> Error
8392 end .
8493
8594offset (Base , N ) ->
0 commit comments