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:
parent
b99cde9599
commit
91f751ddc6
3 changed files with 41 additions and 11 deletions
|
@ -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) ->
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue