diff options
Diffstat (limited to 'merge/src/merge_util.erl')
-rw-r--r-- | merge/src/merge_util.erl | 74 |
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. |