From 6fdc0f0ae77d6aaefd175277fa8355089f41806a Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Wed, 28 Jan 2015 17:29:58 +0100 Subject: Perform frontend index writes in two phases --- src/db.erl | 25 ++++++++++++++++++------- src/frontend.erl | 6 +++++- src/perm.erl | 26 ++++++++++++++++++++------ 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/db.erl b/src/db.erl index d2e0814..0541678 100644 --- a/src/db.erl +++ b/src/db.erl @@ -6,10 +6,11 @@ %% API. -export([start_link/0, stop/0]). --export([add/2, add_entryhash/2, add_index/2, set_treesize/1, size/0]). +-export([add/2, add_entryhash/2, add_index_nosync/2, set_treesize/1, size/0]). -export([get_by_index/1, get_by_indices/3, get_by_leaf_hash/1]). -export([get_by_entry_hash/1, entry_for_leafhash/1, leafhash_for_index/1]). -export([leafhash_for_indices/2, indexsize/0]). +-export([indexforhash_sync/2, index_sync/0]). %% gen_server callbacks. -export([init/1, handle_call/3, terminate/2, handle_cast/2, handle_info/2, code_change/3]). @@ -48,9 +49,9 @@ add_entryhash(LeafHash, EntryHash) -> ok = perm:ensurefile(entryhash_root_path(), EntryHash, LeafHash), ok. --spec add_index(binary(), non_neg_integer()) -> ok. -add_index(LeafHash, Index) -> - call(?MODULE, {add_index, {LeafHash, Index}}). +-spec add_index_nosync(binary(), non_neg_integer()) -> ok. +add_index_nosync(LeafHash, Index) -> + call(?MODULE, {add_index_nosync, {LeafHash, Index}}). -spec set_treesize(non_neg_integer()) -> ok. set_treesize(Size) -> @@ -177,8 +178,18 @@ get_by_indices_helper(Start, End) -> handle_call(stop, _From, State) -> {stop, normal, stopped, State}; -handle_call({add_index, {LeafHash, Index}}, _From, State) -> - ok = perm:ensurefile(indexforhash_root_path(), - LeafHash, integer_to_binary(Index)), +handle_call({add_index_nosync, {LeafHash, Index}}, _From, State) -> + ok = perm:ensurefile_nosync(indexforhash_root_path(), + LeafHash, integer_to_binary(Index)), ok = index:add(index_path(), Index, LeafHash), {reply, ok, State}. + +indexforhash_sync(LeafHash, Index) -> + ok = perm:ensurefile(indexforhash_root_path(), + LeafHash, integer_to_binary(Index)), + ok. + +index_sync() -> + Basepath = index_path(), + ok = util:fsync([Basepath, filename:dirname(Basepath)]), + ok. diff --git a/src/frontend.erl b/src/frontend.erl index 6fc2fd5..b2244de 100644 --- a/src/frontend.erl +++ b/src/frontend.erl @@ -29,8 +29,12 @@ request(post, "ct/frontend/sendlog", Input) -> Indices = lists:seq(Start, Start + length(Hashes) - 1), lists:foreach(fun ({Hash, Index}) -> - ok = db:add_index(Hash, Index) + ok = db:add_index_nosync(Hash, Index) end, lists:zip(Hashes, Indices)), + lists:foreach(fun ({Hash, Index}) -> + ok = db:indexforhash_sync(Hash, Index) + end, lists:zip(Hashes, Indices)), + ok = db:index_sync(), success({[{result, <<"ok">>}]}) end; diff --git a/src/perm.erl b/src/perm.erl index 9f02b55..614656a 100644 --- a/src/perm.erl +++ b/src/perm.erl @@ -2,7 +2,7 @@ %%% See LICENSE for licensing information. -module(perm). --export([ensurefile/3, readfile/2]). +-export([ensurefile/3, ensurefile_nosync/3, readfile/2]). -spec readfile_and_verify(string(), binary()) -> ok | differ | {error, atom()}. readfile_and_verify(Name, Content) -> @@ -49,13 +49,21 @@ path_for_key(Rootdir, Key) -> -spec ensurefile(string(), binary(), binary()) -> ok | differ. ensurefile(Rootdir, Key, Content) -> + ensurefile(Rootdir, Key, Content, sync). + +-spec ensurefile_nosync(string(), binary(), binary()) -> ok | differ. +ensurefile_nosync(Rootdir, Key, Content) -> + ensurefile(Rootdir, Key, Content, nosync). + +ensurefile(Rootdir, Key, Content, Syncflag) -> lager:debug("dir ~p key ~p", [Rootdir, Key]), {Dirs, Path} = path_for_key(Rootdir, Key), case readfile_and_verify(Path, Content) of ok -> lager:debug("key ~p existed, fsync", [Key]), - util:fsync([Path, Rootdir | Dirs]), - lager:debug("key ~p fsynced", [Key]); + ok = util:fsync([Path, Rootdir | Dirs]), + lager:debug("key ~p fsynced", [Key]), + ok; differ -> lager:debug("key ~p existed, was different", [Key]), differ; @@ -67,9 +75,15 @@ ensurefile(Rootdir, Key, Content) -> NurseryName = Rootdir ++ "nursery/" ++ util:tempfilename(hex:bin_to_hexstr(Key)), util:write_tempfile_and_rename(Path, NurseryName, Content), - lager:debug("key ~p added, fsync", [Key]), - util:fsync([Path, Rootdir | Dirs]), - lager:debug("key ~p fsynced", [Key]); + case Syncflag of + sync -> + lager:debug("key ~p added, fsync", [Key]), + ok = util:fsync([Path, Rootdir | Dirs]), + lager:debug("key ~p fsynced", [Key]), + ok; + nosync -> + ok + end; {error, Error} -> util:exit_with_error(Error, readfile, "Error reading file") end. -- cgit v1.1