anchor.diff:      NewState = flush_buffer(State),
       file:datasync(NewState#state.file),
       NewState.
  +
  +rotate_files(#state{path = Path,
  +                    rotation_num_files = NumFiles}) ->
  +    rotate_files_loop(Path, NumFiles - 1).
  +
  +rotate_files_loop(Path, 0) ->
  +    case file:delete(Path) of
  +        ok ->
  +            ok;
  +        Error ->
  +            Error
  +    end;
  +rotate_files_loop(Path, 1) ->
  +    To = Path ++ ".1",
  +    case do_rotate_file(Path, To) of
  +        ok ->
  +            ok;
  +        Error ->
  +            Error
  +    end;
  +rotate_files_loop(Path, N) ->
  +    From = Path ++ "." ++ integer_to_list(N - 1),
  +    To = Path ++ "." ++ integer_to_list(N),
  +
  +    case do_rotate_file(From, To) of
  +        ok ->
  +            rotate_files_loop(Path, N - 1);
  +        Error ->
  +            Error
  +    end.
  +
  +do_rotate_file(From, To) ->
  +    case file:read_file_info(From) of
  +        {error, enoent} ->
  +            ok;
  +        {error, _} = Error ->
  +            Error;
  +        {ok, _} ->
  +            case file:rename(From, To) of
  +                ok ->
  +                    ok;
  +                Error ->
  +                    Error
  +            end
  +    end.
  +
  +maybe_rotate_files(#state{file_size = FileSize,
  +                          rotation_size = RotSize} = State)
  +  when RotSize =/= 0, FileSize >= RotSize ->
  +    ok = rotate_files(State),
  +    open_log_file(State);
  +maybe_rotate_files(State) ->
  +    State.
  +
  +open_log_file(#state{path = Path,
  +                     file = OldFile} = State) ->
  +    case OldFile of
  +        undefined ->
  +            ok;
  +        _ ->
  +            file:close(OldFile)
  +    end,
  +
  +    {ok, File, #file_info{size = Size}} = open_file(Path),
  +    State#state{file = File,
  +                file_size = Size}.
  +
  +open_file(Path) ->
  +    case file:read_file_info(Path) of
  +        {ok, Info} ->
  +            do_open_file(Path, Info);
  +        {error, enoent} ->
  +            case file:open(Path, [raw, append, binary]) of
  +                {ok, File} ->
  +                    file:close(File),
  +                    open_file(Path);
  +                Error ->
  +                    Error
  +            end;
  +        Error ->
  +            Error
  +    end.
  +
  +do_open_file(Path, #file_info{inode = Inode}) ->
  +    case file:open(Path, [raw, append, binary]) of
  +        {ok, File} ->
  +            case file:read_file_info(Path) of
  +                {ok, #file_info{inode = Inode} = Info} -> % Inode is bound
  +                    {ok, File, Info};
  +                {ok, OtherInfo} ->
  +                    file:close(File),
  +                    do_open_file(Path, OtherInfo);
  +                Error ->
  +                    file:close(File),
  +                    Error
  +            end;
  +        Error ->
  +            Error
  +    end.
  
positive.code:     {ok, State}.
  
  %% internal functions
  open_log(Path) ->
      {ok, F} = file:open(Path, [raw, append, binary]),
      F.
  
  log_msg(Msg, #state{buffer = Buffer,
                      buffer_size = BufferSize,
                      batch_size = BatchSize} = State) ->
  
negative.code: -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
           terminate/2, code_change/3]).
  
  -include_lib("kernel/include/file.hrl").
  -include("ale.hrl").
  
  -record(state, {
            path :: string(),
            file :: undefined | file:io_device(),
            file_size :: integer(),
            buffer :: binary(),
            buffer_size :: integer(),
            flush_timer :: undefined | reference(),
  
            batch_size :: pos_integer(),
            batch_timeout :: pos_integer(),
            rotation_size :: non_neg_integer(),
            rotation_num_files :: pos_integer()
           }).
  
  start_link(Name, Path) ->
  