Garbage collect backups

If ther are backups made to the same folder, need to remove any files from that folder that are not included in this backup.

Some initial testing, needs more.
This commit is contained in:
Martin Sumner 2018-09-07 14:21:01 +01:00
parent b99cde9599
commit 91f751ddc6
3 changed files with 41 additions and 11 deletions

View file

@ -1169,7 +1169,9 @@ handle_call(hot_backup, _From, State) when State#state.head_only == false ->
end end
end, end,
InkerOpts = InkerOpts =
#inker_options{start_snapshot=true, source_inker=State#state.inker}, #inker_options{start_snapshot = true,
source_inker = State#state.inker,
bookies_pid = self()},
{ok, Snapshot} = leveled_inker:ink_snapstart(InkerOpts), {ok, Snapshot} = leveled_inker:ink_snapstart(InkerOpts),
{reply, {async, BackupFun(Snapshot)}, State}; {reply, {async, BackupFun(Snapshot)}, State};
handle_call(close, _From, State) -> handle_call(close, _From, State) ->

View file

@ -301,7 +301,7 @@ ink_doom(Pid) ->
%% %%
%% The InitAccFun should return an initial batch accumulator for each subfold. %% The InitAccFun should return an initial batch accumulator for each subfold.
%% It is a 2-arity function that takes a filename and a MinSQN as an input %% It is a 2-arity function that takes a filename and a MinSQN as an input
%% potentially to be use din logging %% potentially to be used in logging
%% %%
%% The BatchFun is a two arity function that should take as inputs: %% The BatchFun is a two arity function that should take as inputs:
%% An overall accumulator %% An overall accumulator
@ -563,6 +563,7 @@ handle_call(roll, _From, State) ->
{reply, ok, State}; {reply, ok, State};
_ -> _ ->
NewSQN = State#state.journal_sqn + 1, NewSQN = State#state.journal_sqn + 1,
SWroll = os:timestamp(),
{NewJournalP, Manifest1, NewManSQN} = {NewJournalP, Manifest1, NewManSQN} =
roll_active(State#state.active_journaldb, roll_active(State#state.active_journaldb,
State#state.manifest, State#state.manifest,
@ -570,6 +571,7 @@ handle_call(roll, _From, State) ->
State#state.cdb_options, State#state.cdb_options,
State#state.root_path, State#state.root_path,
State#state.manifest_sqn), State#state.manifest_sqn),
leveled_log:log_timer("I0024", [NewSQN], SWroll),
{reply, ok, State#state{journal_sqn = NewSQN, {reply, ok, State#state{journal_sqn = NewSQN,
manifest = Manifest1, manifest = Manifest1,
manifest_sqn = NewManSQN, manifest_sqn = NewManSQN,
@ -580,11 +582,14 @@ handle_call({backup, BackupPath}, _from, State)
SW = os:timestamp(), SW = os:timestamp(),
BackupJFP = filepath(filename:join(BackupPath, ?JOURNAL_FP), journal_dir), BackupJFP = filepath(filename:join(BackupPath, ?JOURNAL_FP), journal_dir),
ok = filelib:ensure_dir(BackupJFP), ok = filelib:ensure_dir(BackupJFP),
{ok, CurrentFNs} = file:list_dir(BackupJFP),
leveled_log:log("I0023", [length(CurrentFNs)]),
BackupFun = BackupFun =
fun({SQN, FN, PidR, LastKey}, Acc) -> fun({SQN, FN, PidR, LastKey}, {ManAcc, FTRAcc}) ->
case SQN < State#state.journal_sqn of case SQN < State#state.journal_sqn of
true -> true ->
BaseFN = filename:basename(FN), BaseFN = filename:basename(FN),
ExtendedBaseFN = BaseFN ++ "." ++ ?JOURNAL_FILEX,
BackupName = filename:join(BackupJFP, BaseFN), BackupName = filename:join(BackupJFP, BaseFN),
true = leveled_cdb:finished_rolling(PidR), true = leveled_cdb:finished_rolling(PidR),
case file:make_link(FN ++ "." ++ ?JOURNAL_FILEX, case file:make_link(FN ++ "." ++ ?JOURNAL_FILEX,
@ -594,16 +599,32 @@ handle_call({backup, BackupPath}, _from, State)
{error, eexist} -> {error, eexist} ->
ok ok
end, end,
[{SQN, BackupName, PidR, LastKey}|Acc]; {[{SQN, BackupName, PidR, LastKey}|ManAcc],
[ExtendedBaseFN|FTRAcc]};
false -> false ->
leveled_log:log("I0021", [FN, SQN, State#state.journal_sqn]), leveled_log:log("I0021", [FN, SQN, State#state.journal_sqn]),
Acc {ManAcc, FTRAcc}
end end
end, end,
BackupManifest = {BackupManifest, FilesToRetain} =
lists:foldr(BackupFun, lists:foldr(BackupFun,
[], {[], []},
leveled_imanifest:to_list(State#state.manifest)), leveled_imanifest:to_list(State#state.manifest)),
FilesToRemove = lists:subtract(CurrentFNs, FilesToRetain),
RemoveFun =
fun(RFN) ->
leveled_log:log("I0022", [RFN]),
RemoveFile = filename:join(BackupJFP, RFN),
case filelib:is_file(RemoveFile)
and not filelib:is_dir(RemoveFile) of
true ->
ok = file:delete(RemoveFile);
false ->
ok
end
end,
lists:foreach(RemoveFun, FilesToRemove),
leveled_imanifest:writer(leveled_imanifest:from_list(BackupManifest), leveled_imanifest:writer(leveled_imanifest:from_list(BackupManifest),
State#state.manifest_sqn, State#state.manifest_sqn,
filename:join(BackupPath, ?JOURNAL_FP)), filename:join(BackupPath, ?JOURNAL_FP)),
@ -793,6 +814,7 @@ put_object(LedgerKey, Object, KeyChanges, State) ->
State#state{journal_sqn=NewSQN}, State#state{journal_sqn=NewSQN},
byte_size(JournalBin)}; byte_size(JournalBin)};
roll -> roll ->
SWroll = os:timestamp(),
{NewJournalP, Manifest1, NewManSQN} = {NewJournalP, Manifest1, NewManSQN} =
roll_active(ActiveJournal, roll_active(ActiveJournal,
State#state.manifest, State#state.manifest,
@ -800,6 +822,7 @@ put_object(LedgerKey, Object, KeyChanges, State) ->
State#state.cdb_options, State#state.cdb_options,
State#state.root_path, State#state.root_path,
State#state.manifest_sqn), State#state.manifest_sqn),
leveled_log:log_timer("I0008", [], SWroll),
ok = leveled_cdb:cdb_put(NewJournalP, ok = leveled_cdb:cdb_put(NewJournalP,
JournalKey, JournalKey,
JournalBin), JournalBin),
@ -837,7 +860,6 @@ get_object(LedgerKey, SQN, Manifest, ToIgnoreKeyChanges) ->
%% Roll the active journal, and start a new active journal, updating the %% Roll the active journal, and start a new active journal, updating the
%% manifest %% manifest
roll_active(ActiveJournal, Manifest, NewSQN, CDBopts, RootPath, ManifestSQN) -> roll_active(ActiveJournal, Manifest, NewSQN, CDBopts, RootPath, ManifestSQN) ->
SWroll = os:timestamp(),
LastKey = leveled_cdb:cdb_lastkey(ActiveJournal), LastKey = leveled_cdb:cdb_lastkey(ActiveJournal),
ok = leveled_cdb:cdb_roll(ActiveJournal), ok = leveled_cdb:cdb_roll(ActiveJournal),
Manifest0 = Manifest0 =
@ -847,7 +869,7 @@ roll_active(ActiveJournal, Manifest, NewSQN, CDBopts, RootPath, ManifestSQN) ->
{_, _, NewJournalP, _} = ManEntry, {_, _, NewJournalP, _} = ManEntry,
Manifest1 = leveled_imanifest:add_entry(Manifest0, ManEntry, true), Manifest1 = leveled_imanifest:add_entry(Manifest0, ManEntry, true),
ok = leveled_imanifest:writer(Manifest1, ManifestSQN + 1, RootPath), ok = leveled_imanifest:writer(Manifest1, ManifestSQN + 1, RootPath),
leveled_log:log_timer("I0008", [], SWroll),
{NewJournalP, Manifest1, ManifestSQN + 1}. {NewJournalP, Manifest1, ManifestSQN + 1}.
-spec key_check(leveled_codec:ledger_key(), -spec key_check(leveled_codec:ledger_key(),

View file

@ -284,7 +284,13 @@
{info, "Journal backup completed to path=~s with file_count=~w"}}, {info, "Journal backup completed to path=~s with file_count=~w"}},
{"I0021", {"I0021",
{info, "Ingoring filename=~s with SQN=~w and JournalSQN=~w"}}, {info, "Ingoring filename=~s with SQN=~w and JournalSQN=~w"}},
{"I0022",
{info, "Removing filename=~s from backup folder as not in backup"}},
{"I0023",
{info, "Backup commencing into folder with ~w existing files"}},
{"I0024",
{info, "Prompted roll at NewSQN=~w"}},
{"IC001", {"IC001",
{info, "Closed for reason ~w so maybe leaving garbage"}}, {info, "Closed for reason ~w so maybe leaving garbage"}},
{"IC002", {"IC002",