summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMagnus Ahltorp <map@kth.se>2014-10-19 01:37:29 +0200
committerMagnus Ahltorp <map@kth.se>2014-10-24 15:36:35 +0200
commit80c8ef847d996af04ec677a79555d640733641f2 (patch)
tree6563a0d718122e3228a00028e048dec649c1d83f /src
parent6f477e27dcbb8ecf24947d473186e8984cf87867 (diff)
db:get_by_leaf_hash(): Return notfound instead of crashing when no entry could be found.
db:get_by_entry_hash(): Don't fetch index, isn't used and might not exist. index:add(): Allow writes at exiting indicies.
Diffstat (limited to 'src')
-rw-r--r--src/db.erl25
-rw-r--r--src/index.erl64
2 files changed, 57 insertions, 32 deletions
diff --git a/src/db.erl b/src/db.erl
index 6315ae5..6fce8a3 100644
--- a/src/db.erl
+++ b/src/db.erl
@@ -103,7 +103,12 @@ entry_for_leafhash(LeafHash) ->
perm:readfile(entry_root_path(), LeafHash).
index_for_leafhash(LeafHash) ->
- binary_to_integer(perm:readfile(indexforhash_root_path(), LeafHash)).
+ case perm:readfile(indexforhash_root_path(), LeafHash) of
+ noentry ->
+ noentry;
+ Index ->
+ binary_to_integer(Index)
+ end.
leafhash_for_index(Index) ->
index:get(index_path(), Index).
@@ -148,9 +153,17 @@ handle_call({get_by_index, Index}, _From, State) ->
{reply, R, State};
handle_call({get_by_leaf_hash, LeafHash}, _From, State) ->
- Entry = entry_for_leafhash(LeafHash),
- Index = index_for_leafhash(LeafHash),
- R = {Index, LeafHash, Entry},
+ R = case entry_for_leafhash(LeafHash) of
+ noentry ->
+ notfound;
+ Entry ->
+ case index_for_leafhash(LeafHash) of
+ noentry ->
+ notfound;
+ Index ->
+ {Index, LeafHash, Entry}
+ end
+ end,
{reply, R, State};
handle_call({get_by_entry_hash, EntryHash}, _From, State) ->
@@ -159,7 +172,7 @@ handle_call({get_by_entry_hash, EntryHash}, _From, State) ->
notfound;
LeafHash ->
Entry = entry_for_leafhash(LeafHash),
- Index = index_for_leafhash(LeafHash),
- {Index, LeafHash, Entry}
+ %% Don't fetch index, isn't used and might not exist
+ {notfetched, LeafHash, Entry}
end,
{reply, R, State}.
diff --git a/src/index.erl b/src/index.erl
index 7871215..5169fbb 100644
--- a/src/index.erl
+++ b/src/index.erl
@@ -1,17 +1,18 @@
%%% Copyright (c) 2014, NORDUnet A/S.
%%% See LICENSE for licensing information.
-%% Implements an interface to a file pair (basename and basename.chksum)
-%% that stores an ordered list of fixed-size entries. Entries can be
-%% added at the end and are retrieved by index. The list can also be
-%% truncated.
+%% Implements an interface to a file pair (basename and
+%% basename.chksum) that stores an ordered list of fixed-size entries.
+%% Entries can be added at the end and are retrieved by index. Entries
+%% can also be added at already existing indices, but then the
+%% contents must be the same.
%%
-%% Writes(add, truncate, addlast) need to be serialized.
+%% Writes(add, addlast) need to be serialized.
%% TODO: Checksums
-module(index).
--export([get/2, add/3, addlast/2, truncate/2]).
+-export([get/2, add/3, addlast/2]).
-define(ENTRYSIZE, 32).
-define(ENTRYSIZEINFILE, (?ENTRYSIZE*2+1)).
@@ -21,27 +22,38 @@ add(Basepath, Index, Entry) when is_binary(Entry), size(Entry) == ?ENTRYSIZE ->
case file:open(Basepath, [read, write, binary]) of
{ok, File} ->
{ok, Position} = file:position(File, eof),
- case Index of
- last when Position rem ?ENTRYSIZEINFILE == 0 ->
- ok;
- Index when is_integer(Index),
- Index * ?ENTRYSIZEINFILE == Position ->
- ok
- end,
+ Mode = case Index of
+ last when Position rem ?ENTRYSIZEINFILE == 0 ->
+ write;
+ Index when is_integer(Index),
+ Index * ?ENTRYSIZEINFILE == Position ->
+ write;
+ Index when is_integer(Index),
+ Index * ?ENTRYSIZEINFILE < Position ->
+ read;
+ _ ->
+ util:exit_with_error(invalid, writefile,
+ "Index not valid")
+ end,
EntryText = hex:bin_to_hexstr(Entry) ++ "\n",
- ok = file:write(File, EntryText),
- ok = file:close(File),
- util:fsync([Basepath, filename:dirname(Basepath)]);
- {error, Error} ->
- util:exit_with_error(Error, writefile,
- "Error opening file for writing")
- end.
-
-truncate(Basepath, Index) ->
- case file:open(Basepath, [read, write, binary]) of
- {ok, File} ->
- {ok, _Position} = file:position(File, Index * ?ENTRYSIZEINFILE),
- ok = file:truncate(File),
+ case Mode of
+ write ->
+ ok = file:write(File, EntryText);
+ read ->
+ {ok, _Position} =
+ file:position(File, {bof, Index * ?ENTRYSIZEINFILE}),
+ {ok, OldEntryText} = file:read(File, ?ENTRYSIZEINFILE),
+ %% check that the written content is the same as
+ %% the old content
+ case binary_to_list(OldEntryText) of
+ EntryText ->
+ ok;
+ _ ->
+ util:exit_with_error(invalid, writefile,
+ "Written content not the" ++
+ " same as old content")
+ end
+ end,
ok = file:close(File),
util:fsync([Basepath, filename:dirname(Basepath)]);
{error, Error} ->