foldheads_bybucket adds segment list support
Accelerate queries for foldheads_bybucket as well
This commit is contained in:
parent
6beeadc7d8
commit
c8ad39b33b
5 changed files with 73 additions and 66 deletions
|
@ -679,12 +679,6 @@ get_runner(State, {keylist, Tag, Bucket, FoldAccT}) ->
|
||||||
leveled_runner:bucketkey_query(SnapFun, Tag, Bucket, FoldAccT);
|
leveled_runner:bucketkey_query(SnapFun, Tag, Bucket, FoldAccT);
|
||||||
|
|
||||||
%% Set of runners for object or metadata folds
|
%% Set of runners for object or metadata folds
|
||||||
get_runner(State,
|
|
||||||
{foldheads_allkeys, Tag, FoldFun, JournalCheck, SnapPreFold}) ->
|
|
||||||
SnapType = snaptype_by_presence(JournalCheck),
|
|
||||||
SnapFun = return_snapfun(State, SnapType, no_lookup, true, SnapPreFold),
|
|
||||||
leveled_runner:foldheads_allkeys(SnapFun, Tag, FoldFun,
|
|
||||||
JournalCheck, false);
|
|
||||||
get_runner(State,
|
get_runner(State,
|
||||||
{foldheads_allkeys,
|
{foldheads_allkeys,
|
||||||
Tag, FoldFun,
|
Tag, FoldFun,
|
||||||
|
@ -702,14 +696,14 @@ get_runner(State,
|
||||||
{foldheads_bybucket,
|
{foldheads_bybucket,
|
||||||
Tag, Bucket, KeyRange,
|
Tag, Bucket, KeyRange,
|
||||||
FoldFun,
|
FoldFun,
|
||||||
JournalCheck, SnapPreFold}) ->
|
JournalCheck, SnapPreFold, SegmentList}) ->
|
||||||
{StartKey, EndKey, SnapQ} = return_ledger_keyrange(Tag, Bucket, KeyRange),
|
{StartKey, EndKey, SnapQ} = return_ledger_keyrange(Tag, Bucket, KeyRange),
|
||||||
SnapType = snaptype_by_presence(JournalCheck),
|
SnapType = snaptype_by_presence(JournalCheck),
|
||||||
SnapFun = return_snapfun(State, SnapType, SnapQ, true, SnapPreFold),
|
SnapFun = return_snapfun(State, SnapType, SnapQ, true, SnapPreFold),
|
||||||
leveled_runner:foldheads_bybucket(SnapFun,
|
leveled_runner:foldheads_bybucket(SnapFun,
|
||||||
{Tag, StartKey, EndKey},
|
{Tag, StartKey, EndKey},
|
||||||
FoldFun,
|
FoldFun,
|
||||||
JournalCheck);
|
JournalCheck, SegmentList);
|
||||||
get_runner(State,
|
get_runner(State,
|
||||||
{foldobjects_bybucket,
|
{foldobjects_bybucket,
|
||||||
Tag, Bucket, KeyRange,
|
Tag, Bucket, KeyRange,
|
||||||
|
@ -1322,8 +1316,7 @@ foldobjects_vs_hashtree_testto() ->
|
||||||
{foldheads_allkeys,
|
{foldheads_allkeys,
|
||||||
?STD_TAG,
|
?STD_TAG,
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, true, false}),
|
||||||
true}),
|
|
||||||
KeyHashList3 = HTFolder3(),
|
KeyHashList3 = HTFolder3(),
|
||||||
?assertMatch(KeyHashList1, lists:usort(KeyHashList3)),
|
?assertMatch(KeyHashList1, lists:usort(KeyHashList3)),
|
||||||
|
|
||||||
|
@ -1342,8 +1335,7 @@ foldobjects_vs_hashtree_testto() ->
|
||||||
{foldheads_allkeys,
|
{foldheads_allkeys,
|
||||||
?STD_TAG,
|
?STD_TAG,
|
||||||
FoldHeadsFun2,
|
FoldHeadsFun2,
|
||||||
false,
|
false, false, false}),
|
||||||
false}),
|
|
||||||
KeyHashList4 = HTFolder4(),
|
KeyHashList4 = HTFolder4(),
|
||||||
?assertMatch(KeyHashList1, lists:usort(KeyHashList4)),
|
?assertMatch(KeyHashList1, lists:usort(KeyHashList4)),
|
||||||
|
|
||||||
|
@ -1413,8 +1405,7 @@ foldobjects_vs_foldheads_bybucket_testto() ->
|
||||||
"BucketA",
|
"BucketA",
|
||||||
all,
|
all,
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, true, false}),
|
||||||
true}),
|
|
||||||
KeyHashList2A = HTFolder2A(),
|
KeyHashList2A = HTFolder2A(),
|
||||||
{async, HTFolder2B} =
|
{async, HTFolder2B} =
|
||||||
book_returnfolder(Bookie1,
|
book_returnfolder(Bookie1,
|
||||||
|
@ -1423,8 +1414,7 @@ foldobjects_vs_foldheads_bybucket_testto() ->
|
||||||
"BucketB",
|
"BucketB",
|
||||||
all,
|
all,
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, false, false}),
|
||||||
false}),
|
|
||||||
KeyHashList2B = HTFolder2B(),
|
KeyHashList2B = HTFolder2B(),
|
||||||
|
|
||||||
?assertMatch(true,
|
?assertMatch(true,
|
||||||
|
@ -1439,8 +1429,7 @@ foldobjects_vs_foldheads_bybucket_testto() ->
|
||||||
"BucketB",
|
"BucketB",
|
||||||
{"Key", <<"$all">>},
|
{"Key", <<"$all">>},
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, false, false}),
|
||||||
false}),
|
|
||||||
KeyHashList2C = HTFolder2C(),
|
KeyHashList2C = HTFolder2C(),
|
||||||
{async, HTFolder2D} =
|
{async, HTFolder2D} =
|
||||||
book_returnfolder(Bookie1,
|
book_returnfolder(Bookie1,
|
||||||
|
@ -1449,8 +1438,7 @@ foldobjects_vs_foldheads_bybucket_testto() ->
|
||||||
"BucketB",
|
"BucketB",
|
||||||
{"Key", "Keyzzzzz"},
|
{"Key", "Keyzzzzz"},
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, true, false}),
|
||||||
true}),
|
|
||||||
KeyHashList2D = HTFolder2D(),
|
KeyHashList2D = HTFolder2D(),
|
||||||
?assertMatch(true,
|
?assertMatch(true,
|
||||||
lists:usort(KeyHashList2B) == lists:usort(KeyHashList2C)),
|
lists:usort(KeyHashList2B) == lists:usort(KeyHashList2C)),
|
||||||
|
@ -1464,8 +1452,7 @@ foldobjects_vs_foldheads_bybucket_testto() ->
|
||||||
"BucketB",
|
"BucketB",
|
||||||
{"Key", "Key4zzzz"},
|
{"Key", "Key4zzzz"},
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, false, false}),
|
||||||
false}),
|
|
||||||
KeyHashList2E = HTFolder2E(),
|
KeyHashList2E = HTFolder2E(),
|
||||||
{async, HTFolder2F} =
|
{async, HTFolder2F} =
|
||||||
book_returnfolder(Bookie1,
|
book_returnfolder(Bookie1,
|
||||||
|
@ -1474,8 +1461,7 @@ foldobjects_vs_foldheads_bybucket_testto() ->
|
||||||
"BucketB",
|
"BucketB",
|
||||||
{"Key5", <<"all">>},
|
{"Key5", <<"all">>},
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, false, false}),
|
||||||
false}),
|
|
||||||
KeyHashList2F = HTFolder2F(),
|
KeyHashList2F = HTFolder2F(),
|
||||||
|
|
||||||
?assertMatch(true, length(KeyHashList2E) > 0),
|
?assertMatch(true, length(KeyHashList2E) > 0),
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
tictactree/5,
|
tictactree/5,
|
||||||
foldheads_allkeys/5,
|
foldheads_allkeys/5,
|
||||||
foldobjects_allkeys/3,
|
foldobjects_allkeys/3,
|
||||||
foldheads_bybucket/4,
|
foldheads_bybucket/5,
|
||||||
foldobjects_bybucket/3,
|
foldobjects_bybucket/3,
|
||||||
foldobjects_byindex/3
|
foldobjects_byindex/3
|
||||||
]).
|
]).
|
||||||
|
@ -247,15 +247,21 @@ foldobjects_bybucket(SnapFun, {Tag, StartKey, EndKey}, FoldFun) ->
|
||||||
FoldFun,
|
FoldFun,
|
||||||
false, false).
|
false, false).
|
||||||
|
|
||||||
-spec foldheads_bybucket(fun(), {atom(), any(), any()}, fun(), boolean()) ->
|
-spec foldheads_bybucket(fun(),
|
||||||
{async, fun()}.
|
{atom(), any(), any()},
|
||||||
|
fun(),
|
||||||
|
boolean(), false|list(integer()))
|
||||||
|
-> {async, fun()}.
|
||||||
%% @doc
|
%% @doc
|
||||||
%% Fold over all object metadata within a given key range in a bucket
|
%% Fold over all object metadata within a given key range in a bucket
|
||||||
foldheads_bybucket(SnapFun, {Tag, StartKey, EndKey}, FoldFun, JournalCheck) ->
|
foldheads_bybucket(SnapFun,
|
||||||
|
{Tag, StartKey, EndKey},
|
||||||
|
FoldFun,
|
||||||
|
JournalCheck, SegmentList) ->
|
||||||
foldobjects(SnapFun,
|
foldobjects(SnapFun,
|
||||||
Tag, StartKey, EndKey,
|
Tag, StartKey, EndKey,
|
||||||
FoldFun,
|
FoldFun,
|
||||||
{true, JournalCheck}, false).
|
{true, JournalCheck}, SegmentList).
|
||||||
|
|
||||||
-spec foldobjects_byindex(fun(), tuple(), fun()) -> {async, fun()}.
|
-spec foldobjects_byindex(fun(), tuple(), fun()) -> {async, fun()}.
|
||||||
%% @doc
|
%% @doc
|
||||||
|
|
|
@ -117,8 +117,7 @@ aae_missingjournal(_Config) ->
|
||||||
{foldheads_allkeys,
|
{foldheads_allkeys,
|
||||||
?RIAK_TAG,
|
?RIAK_TAG,
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, true, false}),
|
||||||
true}),
|
|
||||||
HeadL1 = length(AllHeadF1()),
|
HeadL1 = length(AllHeadF1()),
|
||||||
io:format("Fold head returned ~w objects~n", [HeadL1]),
|
io:format("Fold head returned ~w objects~n", [HeadL1]),
|
||||||
|
|
||||||
|
@ -135,8 +134,7 @@ aae_missingjournal(_Config) ->
|
||||||
{foldheads_allkeys,
|
{foldheads_allkeys,
|
||||||
?RIAK_TAG,
|
?RIAK_TAG,
|
||||||
FoldHeadsFun,
|
FoldHeadsFun,
|
||||||
true,
|
true, true, false}),
|
||||||
true}),
|
|
||||||
HeadL2 = length(AllHeadF2()),
|
HeadL2 = length(AllHeadF2()),
|
||||||
io:format("Fold head returned ~w objects~n", [HeadL2]),
|
io:format("Fold head returned ~w objects~n", [HeadL2]),
|
||||||
true = HeadL2 < HeadL1,
|
true = HeadL2 < HeadL1,
|
||||||
|
|
|
@ -78,47 +78,37 @@ crossbucket_aae(_Config) ->
|
||||||
|
|
||||||
test_singledelta_stores(BookA, BookB, TreeSize, DeltaKey) ->
|
test_singledelta_stores(BookA, BookB, TreeSize, DeltaKey) ->
|
||||||
io:format("Test for single delta with tree size ~w~n", [TreeSize]),
|
io:format("Test for single delta with tree size ~w~n", [TreeSize]),
|
||||||
{B1, K1} = DeltaKey,
|
|
||||||
% Now run a tictac query against both stores to see the extent to which
|
% Now run a tictac query against both stores to see the extent to which
|
||||||
% state between stores is consistent
|
% state between stores is consistent
|
||||||
HeadTicTacFolder =
|
TicTacFolder =
|
||||||
{foldheads_allkeys,
|
{foldheads_allkeys,
|
||||||
?RIAK_TAG,
|
?RIAK_TAG,
|
||||||
{fun head_tictac_foldfun/4,
|
{fun head_tictac_foldfun/4,
|
||||||
{0, leveled_tictac:new_tree(test, TreeSize)}},
|
{0, leveled_tictac:new_tree(test, TreeSize)}},
|
||||||
false,
|
false, true, false},
|
||||||
true},
|
% tictac query by bucket (should be same result as all stores)
|
||||||
|
TicTacByBucketFolder =
|
||||||
|
{foldheads_bybucket,
|
||||||
|
?RIAK_TAG, <<"Bucket">>,
|
||||||
|
all,
|
||||||
|
{fun head_tictac_foldfun/4,
|
||||||
|
{0, leveled_tictac:new_tree(test, TreeSize)}},
|
||||||
|
false, false, false},
|
||||||
|
|
||||||
SW_TT0 = os:timestamp(),
|
DLs = check_tictacfold(BookA, BookB,
|
||||||
{async, BookATreeFolder} =
|
TicTacFolder,
|
||||||
leveled_bookie:book_returnfolder(BookA, HeadTicTacFolder),
|
DeltaKey,
|
||||||
{async, BookBTreeFolder} =
|
TreeSize),
|
||||||
leveled_bookie:book_returnfolder(BookB, HeadTicTacFolder),
|
DLs = check_tictacfold(BookA, BookB,
|
||||||
{CountA, BookATree} = BookATreeFolder(),
|
TicTacByBucketFolder,
|
||||||
{CountB, BookBTree} = BookBTreeFolder(),
|
DeltaKey,
|
||||||
Time_TT0 = timer:now_diff(os:timestamp(), SW_TT0)/1000,
|
TreeSize),
|
||||||
io:format("Two tree folds took ~w milliseconds ~n", [Time_TT0]),
|
|
||||||
|
|
||||||
io:format("Fold over keys revealed counts of ~w and ~w~n",
|
|
||||||
[CountA, CountB]),
|
|
||||||
|
|
||||||
% There should be a single delta between the stores
|
|
||||||
1 = CountA - CountB,
|
|
||||||
|
|
||||||
DLs = leveled_tictac:find_dirtyleaves(BookATree, BookBTree),
|
|
||||||
io:format("Found dirty leaves with Riak fold_heads of ~w~n",
|
|
||||||
[length(DLs)]),
|
|
||||||
true = length(DLs) == 1,
|
|
||||||
ExpSeg = leveled_tictac:keyto_segment32(<<B1/binary, K1/binary>>),
|
|
||||||
TreeSeg = leveled_tictac:get_segment(ExpSeg, TreeSize),
|
|
||||||
[ActualSeg] = DLs,
|
|
||||||
true = TreeSeg == ActualSeg,
|
|
||||||
|
|
||||||
HeadSegmentFolder =
|
HeadSegmentFolder =
|
||||||
{foldheads_allkeys,
|
{foldheads_allkeys,
|
||||||
?RIAK_TAG,
|
?RIAK_TAG,
|
||||||
{get_segment_folder(DLs, TreeSize), []},
|
{get_segment_folder(DLs, TreeSize), []},
|
||||||
false, true},
|
false, true, false},
|
||||||
|
|
||||||
SW_SL0 = os:timestamp(),
|
SW_SL0 = os:timestamp(),
|
||||||
{async, BookASegFolder} =
|
{async, BookASegFolder} =
|
||||||
|
@ -229,6 +219,34 @@ head_tictac_foldfun(B, K, PO, {Count, TreeAcc}) ->
|
||||||
leveled_tictac:add_kv(TreeAcc, {B, K}, PO, ExtractFun)}.
|
leveled_tictac:add_kv(TreeAcc, {B, K}, PO, ExtractFun)}.
|
||||||
|
|
||||||
|
|
||||||
|
check_tictacfold(BookA, BookB, HeadTicTacFolder, {B1, K1}, TreeSize) ->
|
||||||
|
SW_TT0 = os:timestamp(),
|
||||||
|
{async, BookATreeFolder} =
|
||||||
|
leveled_bookie:book_returnfolder(BookA, HeadTicTacFolder),
|
||||||
|
{async, BookBTreeFolder} =
|
||||||
|
leveled_bookie:book_returnfolder(BookB, HeadTicTacFolder),
|
||||||
|
{CountA, BookATree} = BookATreeFolder(),
|
||||||
|
{CountB, BookBTree} = BookBTreeFolder(),
|
||||||
|
Time_TT0 = timer:now_diff(os:timestamp(), SW_TT0)/1000,
|
||||||
|
io:format("Two tree folds took ~w milliseconds ~n", [Time_TT0]),
|
||||||
|
|
||||||
|
io:format("Fold over keys revealed counts of ~w and ~w~n",
|
||||||
|
[CountA, CountB]),
|
||||||
|
|
||||||
|
% There should be a single delta between the stores
|
||||||
|
1 = CountA - CountB,
|
||||||
|
|
||||||
|
DLs = leveled_tictac:find_dirtyleaves(BookATree, BookBTree),
|
||||||
|
io:format("Found dirty leaves with Riak fold_heads of ~w~n",
|
||||||
|
[length(DLs)]),
|
||||||
|
true = length(DLs) == 1,
|
||||||
|
ExpSeg = leveled_tictac:keyto_segment32(<<B1/binary, K1/binary>>),
|
||||||
|
TreeSeg = leveled_tictac:get_segment(ExpSeg, TreeSize),
|
||||||
|
[ActualSeg] = DLs,
|
||||||
|
true = TreeSeg == ActualSeg,
|
||||||
|
DLs.
|
||||||
|
|
||||||
|
|
||||||
summary_from_binary(<<131, _Rest/binary>>=ObjBin) ->
|
summary_from_binary(<<131, _Rest/binary>>=ObjBin) ->
|
||||||
{proxy_object, HeadBin, ObjSize, _Fetcher} = binary_to_term(ObjBin),
|
{proxy_object, HeadBin, ObjSize, _Fetcher} = binary_to_term(ObjBin),
|
||||||
summary_from_binary(HeadBin, ObjSize);
|
summary_from_binary(HeadBin, ObjSize);
|
||||||
|
|
|
@ -150,7 +150,7 @@ many_put_compare(_Config) ->
|
||||||
"Bucket",
|
"Bucket",
|
||||||
all,
|
all,
|
||||||
{FoldObjectsFun, leveled_tictac:new_tree(0, TreeSize)},
|
{FoldObjectsFun, leveled_tictac:new_tree(0, TreeSize)},
|
||||||
false, true},
|
false, true, false},
|
||||||
{async, TreeAObjFolder0} =
|
{async, TreeAObjFolder0} =
|
||||||
leveled_bookie:book_returnfolder(Bookie2, FoldQ0),
|
leveled_bookie:book_returnfolder(Bookie2, FoldQ0),
|
||||||
SWB0Obj = os:timestamp(),
|
SWB0Obj = os:timestamp(),
|
||||||
|
@ -165,7 +165,7 @@ many_put_compare(_Config) ->
|
||||||
"Bucket",
|
"Bucket",
|
||||||
all,
|
all,
|
||||||
{FoldObjectsFun, leveled_tictac:new_tree(0, TreeSize)},
|
{FoldObjectsFun, leveled_tictac:new_tree(0, TreeSize)},
|
||||||
true, true},
|
true, true, false},
|
||||||
{async, TreeAObjFolder1} =
|
{async, TreeAObjFolder1} =
|
||||||
leveled_bookie:book_returnfolder(Bookie2, FoldQ1),
|
leveled_bookie:book_returnfolder(Bookie2, FoldQ1),
|
||||||
SWB1Obj = os:timestamp(),
|
SWB1Obj = os:timestamp(),
|
||||||
|
@ -193,8 +193,7 @@ many_put_compare(_Config) ->
|
||||||
"Bucket",
|
"Bucket",
|
||||||
all,
|
all,
|
||||||
{AltFoldObjectsFun, leveled_tictac:new_tree(0, TreeSize)},
|
{AltFoldObjectsFun, leveled_tictac:new_tree(0, TreeSize)},
|
||||||
false,
|
false, true, false},
|
||||||
true},
|
|
||||||
{async, TreeAAltObjFolder0} =
|
{async, TreeAAltObjFolder0} =
|
||||||
leveled_bookie:book_returnfolder(Bookie2, AltFoldQ0),
|
leveled_bookie:book_returnfolder(Bookie2, AltFoldQ0),
|
||||||
SWB2Obj = os:timestamp(),
|
SWB2Obj = os:timestamp(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue