Add spec and comments to penciller
This commit is contained in:
parent
ee5dc43cfd
commit
dd7b753688
2 changed files with 67 additions and 6 deletions
|
@ -21,11 +21,13 @@
|
||||||
-define(BAND_MASK, ?INTEGER_SIZE - 1).
|
-define(BAND_MASK, ?INTEGER_SIZE - 1).
|
||||||
|
|
||||||
|
|
||||||
|
-type bloom() :: binary().
|
||||||
|
|
||||||
%%%============================================================================
|
%%%============================================================================
|
||||||
%%% API
|
%%% API
|
||||||
%%%============================================================================
|
%%%============================================================================
|
||||||
|
|
||||||
-spec create_bloom(list(integer())) -> binary().
|
-spec create_bloom(list(integer())) -> bloom().
|
||||||
%% @doc
|
%% @doc
|
||||||
%% Create a binary bloom filter from alist of hashes
|
%% Create a binary bloom filter from alist of hashes
|
||||||
create_bloom(HashList) ->
|
create_bloom(HashList) ->
|
||||||
|
@ -51,7 +53,7 @@ create_bloom(HashList) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec check_hash(integer(), binary()) -> boolean().
|
-spec check_hash(integer(), bloom()) -> boolean().
|
||||||
%% @doc
|
%% @doc
|
||||||
%% Check for the presence of a given hash within a bloom
|
%% Check for the presence of a given hash within a bloom
|
||||||
check_hash(_Hash, <<>>) ->
|
check_hash(_Hash, <<>>) ->
|
||||||
|
|
|
@ -943,7 +943,10 @@ sst_filename(ManSQN, Level, Count) ->
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%============================================================================
|
%%%============================================================================
|
||||||
|
|
||||||
|
-spec start_from_file(penciller_options()) -> {ok, pcl_state()}.
|
||||||
|
%% @doc
|
||||||
|
%% Normal start of a penciller (i.e. not a snapshot), needs to read the
|
||||||
|
%% filesystem and reconstruct the ledger from the files that it finds
|
||||||
start_from_file(PCLopts) ->
|
start_from_file(PCLopts) ->
|
||||||
RootPath = PCLopts#penciller_options.root_path,
|
RootPath = PCLopts#penciller_options.root_path,
|
||||||
MaxTableSize =
|
MaxTableSize =
|
||||||
|
@ -1035,6 +1038,12 @@ shutdown_manifest(Manifest)->
|
||||||
leveled_pmanifest:close_manifest(Manifest, EntryCloseFun).
|
leveled_pmanifest:close_manifest(Manifest, EntryCloseFun).
|
||||||
|
|
||||||
|
|
||||||
|
-spec archive_files(list(), list()) -> ok.
|
||||||
|
%% @doc
|
||||||
|
%% Archive any sst files in the folder that have not been used to build the
|
||||||
|
%% ledger at startup. They may have not deeleted as expected, so this saves
|
||||||
|
%% them off as non-SST fies to make it easier for an admin to garbage collect
|
||||||
|
%% theses files
|
||||||
archive_files(RootPath, UsedFileList) ->
|
archive_files(RootPath, UsedFileList) ->
|
||||||
{ok, AllFiles} = file:list_dir(sst_rootpath(RootPath)),
|
{ok, AllFiles} = file:list_dir(sst_rootpath(RootPath)),
|
||||||
FileCheckFun =
|
FileCheckFun =
|
||||||
|
@ -1066,9 +1075,20 @@ archive_files(RootPath, UsedFileList) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|
||||||
|
-spec update_levelzero(integer(), tuple(), integer(), list(), pcl_state())
|
||||||
|
-> pcl_state().
|
||||||
|
%% @doc
|
||||||
|
%% Update the in-memory cache of recent changes for the penciller. This is
|
||||||
|
%% the level zer at the top of the tree.
|
||||||
|
%% Once the update is made, there needs to be a decision to potentially roll
|
||||||
|
%% the level-zero memory to an on-disk level zero sst file. This can only
|
||||||
|
%% happen when the cache has exeeded the size threshold (with some jitter
|
||||||
|
%% to prevent coordination across multiple leveled instances), and when there
|
||||||
|
%% is no level zero file already present, and when there is no manifest change
|
||||||
|
%% pending.
|
||||||
update_levelzero(L0Size, {PushedTree, PushedIdx, MinSQN, MaxSQN},
|
update_levelzero(L0Size, {PushedTree, PushedIdx, MinSQN, MaxSQN},
|
||||||
LedgerSQN, L0Cache, State) ->
|
LedgerSQN, L0Cache, State) ->
|
||||||
SW = os:timestamp(),
|
SW = os:timestamp(), % Time this for logging purposes
|
||||||
Update = leveled_pmem:add_to_cache(L0Size,
|
Update = leveled_pmem:add_to_cache(L0Size,
|
||||||
{PushedTree, MinSQN, MaxSQN},
|
{PushedTree, MinSQN, MaxSQN},
|
||||||
LedgerSQN,
|
LedgerSQN,
|
||||||
|
@ -1116,7 +1136,12 @@ update_levelzero(L0Size, {PushedTree, PushedIdx, MinSQN, MaxSQN},
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec roll_memory(pcl_state(), boolean())
|
||||||
|
-> {pid(), leveled_ebloom:bloom()|none}.
|
||||||
|
%% @doc
|
||||||
|
%% Roll the in-memory cache into a L0 file. If this is done synchronously,
|
||||||
|
%% will return a bloom representing the contents of the file.
|
||||||
|
%%
|
||||||
%% Casting a large object (the levelzero cache) to the gen_server did not lead
|
%% Casting a large object (the levelzero cache) to the gen_server did not lead
|
||||||
%% to an immediate return as expected. With 32K keys in the TreeList it could
|
%% to an immediate return as expected. With 32K keys in the TreeList it could
|
||||||
%% take around 35-40ms.
|
%% take around 35-40ms.
|
||||||
|
@ -1126,7 +1151,6 @@ update_levelzero(L0Size, {PushedTree, PushedIdx, MinSQN, MaxSQN},
|
||||||
%%
|
%%
|
||||||
%% The Wait is set to false to use a cast when calling this in normal operation
|
%% The Wait is set to false to use a cast when calling this in normal operation
|
||||||
%% where as the Wait of true is used at shutdown
|
%% where as the Wait of true is used at shutdown
|
||||||
|
|
||||||
roll_memory(State, false) ->
|
roll_memory(State, false) ->
|
||||||
ManSQN = leveled_pmanifest:get_manifest_sqn(State#state.manifest) + 1,
|
ManSQN = leveled_pmanifest:get_manifest_sqn(State#state.manifest) + 1,
|
||||||
RootPath = sst_rootpath(State#state.root_path),
|
RootPath = sst_rootpath(State#state.root_path),
|
||||||
|
@ -1159,12 +1183,33 @@ roll_memory(State, true) ->
|
||||||
{ok, Constructor, _, Bloom} = R,
|
{ok, Constructor, _, Bloom} = R,
|
||||||
{Constructor, Bloom}.
|
{Constructor, Bloom}.
|
||||||
|
|
||||||
|
|
||||||
|
-spec timed_fetch_mem(tuple(), {integer(), integer()},
|
||||||
|
leveled_pmanifest:manifest(), list(),
|
||||||
|
leveled_pmem:index_array(), pcl_timings())
|
||||||
|
-> {tuple(), pcl_timings()}.
|
||||||
|
%% @doc
|
||||||
|
%% Fetch the result from the penciller, starting by looking in the memory,
|
||||||
|
%% and if it is not found looking down level by level through the LSM tree.
|
||||||
|
%%
|
||||||
|
%% This allows for the request to be timed, and the timing result to be added
|
||||||
|
%% to the aggregate timings - so that timinings per level can be logged and
|
||||||
|
%% the cost of requests dropping levels can be monitored.
|
||||||
|
%%
|
||||||
|
%% the result tuple includes the level at which the result was found.
|
||||||
timed_fetch_mem(Key, Hash, Manifest, L0Cache, L0Index, Timings) ->
|
timed_fetch_mem(Key, Hash, Manifest, L0Cache, L0Index, Timings) ->
|
||||||
SW = os:timestamp(),
|
SW = os:timestamp(),
|
||||||
{R, Level} = fetch_mem(Key, Hash, Manifest, L0Cache, L0Index),
|
{R, Level} = fetch_mem(Key, Hash, Manifest, L0Cache, L0Index),
|
||||||
UpdTimings = update_timings(SW, Timings, R, Level),
|
UpdTimings = update_timings(SW, Timings, R, Level),
|
||||||
{R, UpdTimings}.
|
{R, UpdTimings}.
|
||||||
|
|
||||||
|
|
||||||
|
-spec plain_fetch_mem(tuple(), {integer(), integer()},
|
||||||
|
leveled_pmanifest:manifest(), list(),
|
||||||
|
leveled_pmem:index_array()) -> not_present|tuple().
|
||||||
|
%% @doc
|
||||||
|
%% Fetch the result from the penciller, starting by looking in the memory,
|
||||||
|
%% and if it is not found looking down level by level through the LSM tree.
|
||||||
plain_fetch_mem(Key, Hash, Manifest, L0Cache, L0Index) ->
|
plain_fetch_mem(Key, Hash, Manifest, L0Cache, L0Index) ->
|
||||||
R = fetch_mem(Key, Hash, Manifest, L0Cache, L0Index),
|
R = fetch_mem(Key, Hash, Manifest, L0Cache, L0Index),
|
||||||
element(1, R).
|
element(1, R).
|
||||||
|
@ -1179,6 +1224,14 @@ fetch_mem(Key, Hash, Manifest, L0Cache, L0Index) ->
|
||||||
{KV, memory}
|
{KV, memory}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec fetch(tuple(), {integer(), integer()},
|
||||||
|
leveled_pmanifest:manifest(), integer(),
|
||||||
|
fun()) -> {tuple()|not_present, integer()|basement}.
|
||||||
|
%% @doc
|
||||||
|
%% Fetch from the persisted portion of the LSM tree, checking each level in
|
||||||
|
%% turn until a match is found.
|
||||||
|
%% Levels can be skipped by checking the bloom for the relevant file at that
|
||||||
|
%% level.
|
||||||
fetch(_Key, _Hash, _Manifest, ?MAX_LEVELS + 1, _FetchFun) ->
|
fetch(_Key, _Hash, _Manifest, ?MAX_LEVELS + 1, _FetchFun) ->
|
||||||
{not_present, basement};
|
{not_present, basement};
|
||||||
fetch(Key, Hash, Manifest, Level, FetchFun) ->
|
fetch(Key, Hash, Manifest, Level, FetchFun) ->
|
||||||
|
@ -1217,6 +1270,12 @@ log_slowfetch(T0, R, PID, Level, FetchTolerance) ->
|
||||||
R
|
R
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec compare_to_sqn(tuple()|not_present, integer()) -> boolean().
|
||||||
|
%% @doc
|
||||||
|
%% Check to see if the SQN in the penciller is after the SQN expected for an
|
||||||
|
%% object (used to allow the journal to check compaction status from a cache
|
||||||
|
%% of the ledger - objects with a more recent sequence number can be compacted).
|
||||||
compare_to_sqn(Obj, SQN) ->
|
compare_to_sqn(Obj, SQN) ->
|
||||||
case Obj of
|
case Obj of
|
||||||
not_present ->
|
not_present ->
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue