Add initial system test

Add some initial system tests.  This highlighted issues:
- That files deleted by compaction would be left orphaned and not close,
and would not in fact delete (now deleted by closure only)
- There was an issue on stratup that the first few keys in each journal
would not be re-loaded into the ledger
This commit is contained in:
martinsumner 2016-10-03 23:34:28 +01:00
parent 15f57a0b4a
commit 507428bd0b
9 changed files with 339 additions and 275 deletions

View file

@ -105,10 +105,12 @@
ink_loadpcl/4,
ink_registersnapshot/2,
ink_compactjournal/3,
ink_compactioncomplete/1,
ink_getmanifest/1,
ink_updatemanifest/4,
ink_updatemanifest/3,
ink_print_manifest/1,
ink_close/1,
ink_forceclose/1,
build_dummy_journal/0,
simple_manifest_reader/2,
clean_testdir/1,
@ -135,7 +137,9 @@
registered_snapshots = [] :: list(),
root_path :: string(),
cdb_options :: #cdb_options{},
clerk :: pid()}).
clerk :: pid(),
compaction_pending = false :: boolean(),
is_snapshot = false :: boolean()}).
%%%============================================================================
@ -158,7 +162,10 @@ ink_registersnapshot(Pid, Requestor) ->
gen_server:call(Pid, {snapshot, Requestor}, infinity).
ink_close(Pid) ->
gen_server:call(Pid, close, infinity).
gen_server:call(Pid, {close, false}, infinity).
ink_forceclose(Pid) ->
gen_server:call(Pid, {close, true}, infinity).
ink_loadpcl(Pid, MinSQN, FilterFun, Penciller) ->
gen_server:call(Pid, {load_pcl, MinSQN, FilterFun, Penciller}, infinity).
@ -172,7 +179,7 @@ ink_compactjournal(Pid, Penciller, Timeout) ->
CheckerInitiateFun,
CheckerFilterFun,
Timeout},
infiniy).
infinity).
%% Allows the Checker to be overriden in test, use something other than a
%% penciller
@ -185,14 +192,16 @@ ink_compactjournal(Pid, Checker, InitiateFun, FilterFun, Timeout) ->
Timeout},
infinity).
ink_compactioncomplete(Pid) ->
gen_server:call(Pid, compaction_complete, infinity).
ink_getmanifest(Pid) ->
gen_server:call(Pid, get_manifest, infinity).
ink_updatemanifest(Pid, ManifestSnippet, PromptDeletion, DeletedFiles) ->
ink_updatemanifest(Pid, ManifestSnippet, DeletedFiles) ->
gen_server:call(Pid,
{update_manifest,
ManifestSnippet,
PromptDeletion,
DeletedFiles},
infinity).
@ -213,7 +222,8 @@ init([InkerOpts]) ->
{ActiveJournalDB,
Manifest}} = ink_registersnapshot(SrcInker, Requestor),
{ok, #state{manifest=Manifest,
active_journaldb=ActiveJournalDB}};
active_journaldb=ActiveJournalDB,
is_snapshot=true}};
%% Need to do something about timeout
{_RootPath, false} ->
start_from_file(InkerOpts)
@ -272,7 +282,6 @@ handle_call(get_manifest, _From, State) ->
{reply, State#state.manifest, State};
handle_call({update_manifest,
ManifestSnippet,
PromptDeletion,
DeletedFiles}, _From, State) ->
Man0 = lists:foldl(fun(ManEntry, AccMan) ->
Check = lists:member(ManEntry, DeletedFiles),
@ -291,13 +300,7 @@ handle_call({update_manifest,
ManifestSnippet),
NewManifestSQN = State#state.manifest_sqn + 1,
ok = simple_manifest_writer(Man1, NewManifestSQN, State#state.root_path),
PendingRemovals = case PromptDeletion of
true ->
State#state.pending_removals ++
[{NewManifestSQN, DeletedFiles}];
_ ->
State#state.pending_removals
end,
PendingRemovals = [{NewManifestSQN, DeletedFiles}],
{reply, ok, State#state{manifest=Man1,
manifest_sqn=NewManifestSQN,
pending_removals=PendingRemovals}};
@ -316,9 +319,16 @@ handle_call({compact,
FilterFun,
self(),
Timeout),
{reply, ok, State};
handle_call(close, _From, State) ->
{stop, normal, ok, State};
{reply, ok, State#state{compaction_pending=true}};
handle_call(compaction_complete, _From, State) ->
{reply, ok, State#state{compaction_pending=false}};
handle_call({close, Force}, _From, State) ->
case {State#state.compaction_pending, Force} of
{true, false} ->
{reply, pause, State};
_ ->
{stop, normal, ok, State}
end;
handle_call(Msg, _From, State) ->
io:format("Unexpected message ~w~n", [Msg]),
{reply, error, State}.
@ -330,12 +340,21 @@ handle_info(_Info, State) ->
{noreply, State}.
terminate(Reason, State) ->
io:format("Inker closing journal for reason ~w~n", [Reason]),
io:format("Close triggered with journal_sqn=~w and manifest_sqn=~w~n",
[State#state.journal_sqn, State#state.manifest_sqn]),
io:format("Manifest when closing is: ~n"),
manifest_printer(State#state.manifest),
close_allmanifest(State#state.manifest, State#state.active_journaldb).
case State#state.is_snapshot of
true ->
ok;
false ->
io:format("Inker closing journal for reason ~w~n", [Reason]),
io:format("Close triggered with journal_sqn=~w and manifest_sqn=~w~n",
[State#state.journal_sqn, State#state.manifest_sqn]),
io:format("Manifest when closing is: ~n"),
leveled_iclerk:clerk_stop(State#state.clerk),
lists:foreach(fun({Snap, _SQN}) -> ok = ink_close(Snap) end,
State#state.registered_snapshots),
manifest_printer(State#state.manifest),
close_allmanifest(State#state.manifest, State#state.active_journaldb),
close_allremovals(State#state.pending_removals)
end.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@ -597,6 +616,25 @@ close_allmanifest([H|ManifestT], ActiveJournal) ->
ok = leveled_cdb:cdb_close(Pid),
close_allmanifest(ManifestT, ActiveJournal).
close_allremovals([]) ->
ok;
close_allremovals([{ManifestSQN, Removals}|Tail]) ->
io:format("Closing removals at ManifestSQN=~w~n", [ManifestSQN]),
lists:foreach(fun({LowSQN, FN, Handle}) ->
io:format("Closing removed file with LowSQN=~w" ++
" and filename ~s~n",
[LowSQN, FN]),
if
is_pid(Handle) == true ->
ok = leveled_cdb:cdb_close(Handle);
true ->
io:format("Non pid in removal ~w - test~n",
[Handle])
end
end,
Removals),
close_allremovals(Tail).
roll_pending_journals([TopJournalSQN], Manifest, _RootPath)
when is_integer(TopJournalSQN) ->
@ -621,22 +659,22 @@ load_from_sequence(_MinSQN, _FilterFun, _Penciller, []) ->
load_from_sequence(MinSQN, FilterFun, Penciller, [{LowSQN, FN, Pid}|ManTail])
when LowSQN >= MinSQN ->
io:format("Loading from filename ~s from SQN ~w~n", [FN, MinSQN]),
ok = load_between_sequence(MinSQN,
MinSQN + ?LOADING_BATCH,
FilterFun,
Penciller,
Pid,
undefined),
load_from_sequence(MinSQN, FilterFun, Penciller, ManTail);
{ok, LastMinSQN} = load_between_sequence(MinSQN,
MinSQN + ?LOADING_BATCH,
FilterFun,
Penciller,
Pid,
undefined),
load_from_sequence(LastMinSQN, FilterFun, Penciller, ManTail);
load_from_sequence(MinSQN, FilterFun, Penciller, [_H|ManTail]) ->
load_from_sequence(MinSQN, FilterFun, Penciller, ManTail).
load_between_sequence(MinSQN, MaxSQN, FilterFun, Penciller, CDBpid, StartPos) ->
InitAcc = {MinSQN, MaxSQN, []},
case leveled_cdb:cdb_scan(CDBpid, FilterFun, InitAcc, StartPos) of
{eof, {_AccMinSQN, _AccMaxSQN, AccKL}} ->
{eof, {AccMinSQN, _AccMaxSQN, AccKL}} ->
ok = push_to_penciller(Penciller, AccKL),
ok;
{ok, AccMinSQN};
{LastPosition, {_AccMinSQN, _AccMaxSQN, AccKL}} ->
ok = push_to_penciller(Penciller, AccKL),
load_between_sequence(MaxSQN + 1,
@ -748,7 +786,7 @@ initiate_penciller_snapshot(Penciller) ->
PclOpts = #penciller_options{start_snapshot = true,
source_penciller = Penciller,
requestor = self()},
FilterServer = leveled_penciller:pcl_start(PclOpts),
{ok, FilterServer} = leveled_penciller:pcl_start(PclOpts),
ok = leveled_penciller:pcl_loadsnapshot(FilterServer, []),
FilterServer.
@ -793,6 +831,7 @@ clean_testdir(RootPath) ->
clean_subdir(filepath(RootPath, manifest_dir)).
clean_subdir(DirPath) ->
ok = filelib:ensure_dir(DirPath),
{ok, Files} = file:list_dir(DirPath),
lists:foreach(fun(FN) ->
File = filename:join(DirPath, FN),
@ -921,9 +960,9 @@ rollafile_simplejournal_test() ->
?assertMatch(R2, {{54, "KeyBB"}, {"TestValueBB", []}}),
Man = ink_getmanifest(Ink1),
FakeMan = [{3, "test", dummy}, {1, "other_test", dummy}],
ok = ink_updatemanifest(Ink1, FakeMan, true, Man),
ok = ink_updatemanifest(Ink1, FakeMan, Man),
?assertMatch(FakeMan, ink_getmanifest(Ink1)),
ok = ink_updatemanifest(Ink1, Man, true, FakeMan),
ok = ink_updatemanifest(Ink1, Man, FakeMan),
?assertMatch({{5, "KeyAA"}, {"TestValueAA", []}},
ink_get(Ink1, "KeyAA", 5)),
?assertMatch({{54, "KeyBB"}, {"TestValueBB", []}},
@ -964,7 +1003,6 @@ compact_journal_test() ->
timer:sleep(1000),
CompactedManifest = ink_getmanifest(Ink1),
?assertMatch(1, length(CompactedManifest)),
ink_updatemanifest(Ink1, ActualManifest, true, CompactedManifest),
ink_close(Ink1),
clean_testdir(RootPath).