#!/usr/bin/env escript %% -*- erlang -*- %%! -pa ebin -pa ../lager/ebin -pa ../lager/deps/goldrush/ebin -mode(compile). gentestdata(Size) -> [{crypto:hash(sha256, <>), crypto:hash(sha256, <>)} || E <- lists:seq(0, Size-1)]. genemptytestdata(Size) -> [{crypto:hash(sha256, <>), noentry} || E <- lists:seq(0, Size-1)]. timeprint(Time) -> io_lib:format("~.2fs", [Time/1000000]). testinit(Filename) -> permdb:start_link(testdb, Filename, [{write_flag, write}]). teststop() -> permdb:stop(testdb). constructdata(VSeed, Size) -> A = binary:copy(VSeed, Size div 32), B = binary:part(VSeed, 0, Size rem 32), <>. getvalue_loop([], _Port, _Datasize, _DB) -> none; getvalue_loop([{K, VSeed}|Rest], Port, Datasize, DB) -> V = case VSeed of noentry -> noentry; _ -> constructdata(VSeed, Datasize) end, case permdb:getvalue(DB, K) of V -> getvalue_loop(Rest, Port, Datasize, DB); VOther -> io:format("expected: ~p got: ~p~nkey: ~p~n", [V, VOther, K]), exit(mismatch) end. addvalue_loop([], _Port, _Datasize, _DB) -> none; addvalue_loop([{K, VSeed}|Rest], Port, Datasize, DB) -> V = constructdata(VSeed, Datasize), case permdb:addvalue(DB, K, V) of ok -> addvalue_loop(Rest, Port, Datasize, DB); Other -> io:format("expected: 0 or 1 got: ~p~n", [Other]), exit(mismatch) end. testget(_Filename, TestData, Datasize) -> testget(_Filename, TestData, Datasize, testdb). testget(_Filename, TestData, Datasize, DB) -> getvalue_loop(TestData, none, Datasize, DB), ok. testadd(_Filename, TestData, Datasize) -> testadd(_Filename, TestData, Datasize, testdb). testadd(_Filename, TestData, Datasize, DB) -> addvalue_loop(TestData, none, Datasize, DB), case permdb:commit(DB) of <<0>> -> ok; Other -> io:format("commit expected: 0 got: ~p~n", [Other]), exit(mismatch) end. stop() -> teststop(), receive after 100 -> ok end. main([]) -> {ok, Cwd} = file:get_cwd(), code:add_path(Cwd ++ "/ebin"), Size = 10, Datasize = 99, Filename = "testpermdb", file:delete(Filename), file:delete(Filename ++ ".idx"), {Time1, TestData} = timer:tc(fun () -> gentestdata(Size) end), EmptyTestData = genemptytestdata(Size), io:format("Init with ~p entries: ~s~n", [Size, timeprint(Time1)]), testinit(Filename), Testadd = fun () -> {Time2, ok} = timer:tc(fun () -> testadd(Filename, TestData, Datasize) end), io:format("Add ~p entries: ~s ~.1f entries/s (~.2f microseconds)~n", [Size, timeprint(Time2), Size*1000000/Time2, Time2/Size]) end, Testadd(), Testget = fun () -> {Time2, ok} = timer:tc(fun () -> testget(Filename, TestData, Datasize) end), io:format("Get ~p entries: ~s ~.1f entries/s (~.2f microseconds)~n", [Size, timeprint(Time2), Size*1000000/Time2, Time2/Size]) end, Testget(), stop(), testinit(Filename), Testget(), stop(), file:delete(Filename ++ ".idx"), testinit(Filename), Testget(), stop(), testinit(Filename), Testget(), stop(), {ok, File} = file:open(Filename ++ ".idx", [read, write, binary]), {ok, _Position} = file:position(File, {eof, -120}), ok = file:write(File, <<0>>), file:close(File), testinit(Filename), Testget(), stop(), io:format("------------------------------------------------------------~n", []), file:delete(Filename), file:delete(Filename ++ ".idx"), testinit(Filename), Testemptyget = fun () -> {Time2, ok} = timer:tc(fun () -> testget(Filename, EmptyTestData, Datasize) end), io:format("Get ~p entries: ~s ~.1f entries/s (~.2f microseconds)~n", [Size, timeprint(Time2), Size*1000000/Time2, Time2/Size]) end, Testemptyget(), testadd(Filename, gentestdata(1), 99), testadd(Filename, gentestdata(1+2), 99), testadd(Filename, gentestdata(1+2+3), 99), testadd(Filename, gentestdata(1+2+3+4), 99), testget(Filename, gentestdata(1+2+3+4), 99), stop(), testinit(Filename), permdb:start_link(testdb_ro, Filename, [{write_flag, read}]), testget(Filename, gentestdata(1+2+3+4), 99), testadd(Filename, gentestdata(1+2+3+4+5), 99), testget(Filename, gentestdata(1+2+3+4+5), 99, testdb_ro), permdb:stop(testdb_ro), stop(), ok.