mirror of
https://github.com/valitydev/riak_test.git
synced 2024-11-06 00:25:22 +00:00
Add a more sophisticated equality check to verify
The partition repair test deletes all the data at a partition, and then repairs it from neighbouring partitions. The subset of repaired data that was originally coordinated by the deleted partition's vnode showed up as `notfound` since the latest kv679 changes here https://github.com/basho/riak_kv/pull/1643/. The reason is that the fix in the KV repo adds a new actor to the repaired key's vclock. Prior to this change `verify` in partition_repair.erl did a simple equality check on the binary encoded riak_object values. This change takes into account that a new actor may be in the vclock at the repaired vnode, and uses a semantic equality check based on riak_object merge and riak object equal.
This commit is contained in:
parent
0176494723
commit
1e7e94aacb
@ -169,7 +169,7 @@ kill_repair_verify({Partition, Node}, DataSuffix, Service) ->
|
||||
|
||||
lager:info("Verify ~p on ~p is fully repaired", [Partition, Node]),
|
||||
Data2 = get_data(Service, {Partition, Node}),
|
||||
{Verified, NotFound} = dict:fold(verify(Service, Data2), {0, []}, Stash),
|
||||
{Verified, NotFound} = dict:fold(verify(Node, Service, Data2), {0, []}, Stash),
|
||||
case NotFound of
|
||||
[] -> ok;
|
||||
_ ->
|
||||
@ -188,7 +188,7 @@ kill_repair_verify({Partition, Node}, DataSuffix, Service) ->
|
||||
{ok, [StashB]} = file:consult(StashPathB),
|
||||
ExpectToVerifyB = dict:size(StashB),
|
||||
BeforeData = get_data(Service, B),
|
||||
{VerifiedB, NotFoundB} = dict:fold(verify(Service, BeforeData), {0, []}, StashB),
|
||||
{VerifiedB, NotFoundB} = dict:fold(verify(Node, Service, BeforeData), {0, []}, StashB),
|
||||
case NotFoundB of
|
||||
[] -> ok;
|
||||
_ ->
|
||||
@ -203,7 +203,7 @@ kill_repair_verify({Partition, Node}, DataSuffix, Service) ->
|
||||
{ok, [StashA]} = file:consult(StashPathA),
|
||||
ExpectToVerifyA = dict:size(StashA),
|
||||
AfterData = get_data(Service, A),
|
||||
{VerifiedA, NotFoundA} = dict:fold(verify(Service, AfterData), {0, []}, StashA),
|
||||
{VerifiedA, NotFoundA} = dict:fold(verify(Node, Service, AfterData), {0, []}, StashA),
|
||||
case NotFoundA of
|
||||
[] -> ok;
|
||||
_ ->
|
||||
@ -214,19 +214,23 @@ kill_repair_verify({Partition, Node}, DataSuffix, Service) ->
|
||||
?assertEqual(ExpectToVerifyA, VerifiedA).
|
||||
|
||||
|
||||
verify(riak_kv, DataAfterRepair) ->
|
||||
verify(Node, riak_kv, DataAfterRepair) ->
|
||||
fun(BKey, StashedValue, {Verified, NotFound}) ->
|
||||
StashedData={BKey, StashedValue},
|
||||
case dict:find(BKey, DataAfterRepair) of
|
||||
error -> {Verified, [StashedData|NotFound]};
|
||||
{ok, Value} ->
|
||||
if Value == StashedValue -> {Verified+1, NotFound};
|
||||
true -> {Verified, [StashedData|NotFound]}
|
||||
%% NOTE: since kv679 fixes, the binary values may
|
||||
%% not be equal where a new epoch-actor-entry has
|
||||
%% been added to the repaired value in the vnode
|
||||
case gte(Node, Value, StashedValue, BKey) of
|
||||
true -> {Verified+1, NotFound};
|
||||
false -> {Verified, [StashedData|NotFound]}
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
verify(riak_search, PostingsAfterRepair) ->
|
||||
verify(_Node, riak_search, PostingsAfterRepair) ->
|
||||
fun(IFT, StashedPostings, {Verified, NotFound}) ->
|
||||
StashedPosting={IFT, StashedPostings},
|
||||
case dict:find(IFT, PostingsAfterRepair) of
|
||||
@ -241,6 +245,22 @@ verify(riak_search, PostingsAfterRepair) ->
|
||||
end
|
||||
end.
|
||||
|
||||
%% @private gte checks that `Value' is _at least_ `StashedValue'. With
|
||||
%% the changes for kv679 when a vnode receives a write of a key that
|
||||
%% contains the vnode's id as an entry in the version vector, it adds
|
||||
%% a new actor-epoch-entry to the version vector to guard against data
|
||||
%% loss from repeated events (remember a VV history is supposed to be
|
||||
%% unique!) This function then must deserialise the stashed and vnode
|
||||
%% data and check that they are equal, or if not, the only difference
|
||||
%% is an extra epoch actor in the vnode value's vclock.
|
||||
gte(Node, Value, StashedData, {B, K}) ->
|
||||
VnodeObject = riak_object:from_binary(B, K, Value),
|
||||
StashedObject = riak_object:from_binary(B, K, StashedData),
|
||||
%% NOTE: we need a ring and all that jazz for bucket props, needed
|
||||
%% by merge, so use an RPC to merge on a riak node.
|
||||
Merged = rpc:call(Node, riak_object, syntactic_merge, [VnodeObject, StashedObject]),
|
||||
riak_object:equal(VnodeObject, Merged).
|
||||
|
||||
is_true(X) ->
|
||||
X == true.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user