summaryrefslogtreecommitdiff
path: root/merge/src/merge_util.erl
diff options
context:
space:
mode:
Diffstat (limited to 'merge/src/merge_util.erl')
-rw-r--r--merge/src/merge_util.erl74
1 files changed, 74 insertions, 0 deletions
diff --git a/merge/src/merge_util.erl b/merge/src/merge_util.erl
new file mode 100644
index 0000000..a6b3ac9
--- /dev/null
+++ b/merge/src/merge_util.erl
@@ -0,0 +1,74 @@
+%%% Copyright (c) 2017, NORDUnet A/S.
+%%% See LICENSE for licensing information.
+
+-module(merge_util).
+-export([sendlog/4, sendentries/3]).
+-export([request/2, request/4]).
+
+request(DebugTag, URL) ->
+ request(DebugTag, URL, [], <<>>).
+
+request(DebugTag, URL, Headers, RequestBody) ->
+ case plop_httputil:request(DebugTag, URL, Headers, RequestBody) of
+ {error, Err} ->
+ throw({request_error, request, DebugTag, Err});
+ {failure, {none, StatusCode, none}, _RespHeaders, _Body} ->
+ throw({request_error, failure, DebugTag, StatusCode});
+ {success, {_, StatusCode, _}, _, Body} when StatusCode == 200 ->
+ case (catch mochijson2:decode(Body)) of
+ {error, Err} ->
+ throw({request_error, decode, DebugTag, Err});
+ {struct, PropList} ->
+ {proplists:get_value(<<"result">>, PropList), PropList}
+ end
+ end.
+
+sendlog(NodeAddress, Start, Hashes, Chunksize) ->
+ sendlog_chunk(NodeAddress, Start, lists:split(min(Chunksize, length(Hashes)), Hashes), Chunksize).
+
+sendlog_chunk(_, _, {[], _}, _) ->
+ ok;
+sendlog_chunk(NodeAddress, Start, {Chunk, Rest}, Chunksize) ->
+ ok = sendlog_request(NodeAddress, Start, Chunk),
+ sendlog_chunk(NodeAddress, Start + length(Chunk),
+ lists:split(min(Chunksize, length(Rest)), Rest), Chunksize).
+
+sendlog_request(NodeAddress, Start, Hashes) ->
+ DebugTag = io_lib:format("sendlog ~B:~B", [Start, length(Hashes)]),
+ URL = NodeAddress ++ "sendlog",
+ Headers = [{"Content-Type", "text/json"}],
+ EncodedHashes = [base64:encode(H) || H <- Hashes],
+ RequestBody = list_to_binary(mochijson2:encode({[{"start", Start},
+ {"hashes", EncodedHashes}]})),
+ case request(DebugTag, URL, Headers, RequestBody) of
+ {<<"ok">>, _} ->
+ ok;
+ Err ->
+ throw({request_error, result, DebugTag, Err})
+ end.
+
+sendentries(NodeAddress, Hashes, Chunksize) ->
+ {ChunkOfHashes, RestOfHashes} = lists:split(min(Chunksize, length(Hashes)), Hashes),
+ sendentries_chunk(NodeAddress, {ChunkOfHashes, RestOfHashes}, Chunksize).
+
+sendentries_chunk(_, {[], _}, _) ->
+ ok;
+sendentries_chunk(NodeAddress, {Chunk, Rest}, Chunksize) ->
+ HashesAndEntries = lists:zip(Chunk, [db:entry_for_leafhash(H) || H <- Chunk]),
+ ok = sendentries_request(NodeAddress, HashesAndEntries),
+ sendentries_chunk(NodeAddress,
+ lists:split(min(Chunksize, length(Rest)), Rest),
+ Chunksize).
+
+sendentries_request(NodeAddress, HashesAndEntries) ->
+ DebugTag = io_lib:format("sendentry ~B", [length(HashesAndEntries)]),
+ URL = NodeAddress ++ "sendentry",
+ Headers = [{"Content-Type", "text/json"}],
+ L = mochijson2:encode([[{"entry", base64:encode(E)}, {"treeleafhash", base64:encode(H)}] || {H, E} <- HashesAndEntries]),
+ RequestBody = list_to_binary(L),
+ case request(DebugTag, URL, Headers, RequestBody) of
+ {<<"ok">>, _} ->
+ ok;
+ Err ->
+ throw({request_error, result, DebugTag, Err})
+ end.