Current section

Files

Jump to
ra src ra_log_snapshot_writer.erl
Raw

src/ra_log_snapshot_writer.erl

%% @hidden
-module(ra_log_snapshot_writer).
-behaviour(gen_server).
-include("ra.hrl").
%% API functions
-export([start_link/0,
write_snapshot/3,
write_snapshot_call/2
]).
%% gen_server callbacks
-export([init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3]).
-record(state, {}).
%%%===================================================================
%%% API functions
%%%===================================================================
-spec write_snapshot(pid(), file:filename_all(), ra_log:snapshot()) -> ok.
write_snapshot(From, Dir, Snapshot) ->
gen_server:cast(?MODULE, {write_snapshot, From, Dir, Snapshot}).
-spec write_snapshot_call(file:filename(), ra_log:snapshot()) ->
{ok, File :: file:filename(), Old :: [file:filename()]}.
write_snapshot_call(Dir, Snapshot) ->
gen_server:call(?MODULE, {write_snapshot, Dir, Snapshot}).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([]) ->
{ok, #state{}}.
handle_call({write_snapshot, Dir, Snapshot}, _From, State) ->
Reply = write_snapshot(Dir, Snapshot),
{reply, Reply, State}.
handle_cast({write_snapshot, From, Dir, Snapshot}, State) ->
ok = handle_write_snapshot(From, Dir, Snapshot),
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
handle_write_snapshot(From, Dir, {Index, Term, _, _} = Snapshot) ->
{ok, File, Old} = write_snapshot(Dir, Snapshot),
From ! {ra_log_event, {snapshot_written, {Index, Term}, File, Old}},
ok.
write_snapshot(Dir, Snapshot) ->
case lists:sort(filelib:wildcard(filename:join(Dir, "*.snapshot"))) of
[] ->
% no snapshots - initialise snapshot counter
File = filename:join(Dir, ra_lib:zpad_filename("", "snapshot", 1)),
ok = write(File, Snapshot),
{ok, File, []};
[LastFile | _] = Old ->
File = ra_lib:zpad_filename_incr(LastFile),
ok = write(File, Snapshot),
{ok, File, Old}
end.
write(File, Snapshot) ->
% TODO: snapshots should be checksummed
?INFO("snapshot_writer: Writing file ~p", [File]),
ra_log_snapshot:write(File, Snapshot).