Skip to content

Commit 593fc8e

Browse files
committed
MB-32880: Do not change length of vbucket chain in ...
... ns_janitor when cluster > madhatter. Pre mad-hatter, there is no change to the janitor behaviour. Post mad-hatter changes that follow as a result of the above mentioned change is, 1. Setting the vbucket map is allowed with different length chains. 2. Defer changing vbucket map to rebalance when changing num_replicas i.e., when the admin changes number of replicas for the bucket, do not update the vbucket map until rebalance is performed and not in the janitor prior to rebalance. 3. Explicitly disallow delta-recovery for a bucket if vbucket map of that bucket doesn't contain number of replicas according to Bucket Config. 4. This changeset can result in varied length chains if rebalance was interrupted for any reason. The janitor does not fix the length of the chains. Change-Id: Id7b0c50246796233de4ba688cfd5eaa81a53cad5 Reviewed-on: http://review.couchbase.org/105359 Reviewed-by: Aliaksey Artamonau <[email protected]> Tested-by: Abhijeeth Nuthan <[email protected]>
1 parent 563d34c commit 593fc8e

File tree

4 files changed

+80
-12
lines changed

4 files changed

+80
-12
lines changed

src/ns_bucket.erl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
-include("ns_common.hrl").
1919
-include("ns_config.hrl").
20+
-include("cut.hrl").
2021

2122
-ifdef(TEST).
2223
-include_lib("eunit/include/eunit.hrl").
@@ -27,6 +28,7 @@
2728
bucket_nodes/1,
2829
bucket_type/1,
2930
replication_type/1,
31+
replica_change/1,
3032
create_bucket/3,
3133
credentials/1,
3234
delete_bucket/1,
@@ -712,7 +714,14 @@ set_fast_forward_map(Bucket, Map) ->
712714

713715

714716
set_map(Bucket, Map) ->
715-
true = mb_map:is_valid(Map),
717+
case mb_map:is_valid(Map) of
718+
true ->
719+
ok;
720+
different_length_chains ->
721+
%% Never expect to set map with different_length_chains
722+
%% pre-madhatter.
723+
true = cluster_compat_mode:is_cluster_madhatter()
724+
end,
716725
update_bucket_config(
717726
Bucket,
718727
fun (OldConfig) ->
@@ -833,6 +842,16 @@ past_vbucket_maps(Config) ->
833842
false -> []
834843
end.
835844

845+
replica_change(BucketConfig) ->
846+
replica_change(num_replicas(BucketConfig),
847+
proplists:get_value(map, BucketConfig)).
848+
849+
replica_change(_NumReplicas, undefined) ->
850+
false;
851+
replica_change(NumReplicas, Map) ->
852+
ExpectedChainLength = NumReplicas + 1,
853+
lists:any(?cut(ExpectedChainLength =/= length(_)), Map).
854+
836855
needs_rebalance(BucketConfig, Nodes) ->
837856
Servers = proplists:get_value(servers, BucketConfig, []),
838857
case proplists:get_value(type, BucketConfig) of
@@ -843,6 +862,7 @@ needs_rebalance(BucketConfig, Nodes) ->
843862
_ ->
844863
Map = proplists:get_value(map, BucketConfig),
845864
Map =:= undefined orelse
865+
replica_change(BucketConfig) orelse
846866
lists:sort(Nodes) =/= lists:sort(Servers) orelse
847867
ns_rebalancer:map_options_changed(BucketConfig) orelse
848868
(ns_rebalancer:unbalanced(Map, BucketConfig) andalso

src/ns_janitor.erl

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,17 @@ compute_vbucket_map_fixup(Bucket, BucketConfig, States) ->
363363
ignore -> OldChain;
364364
_ -> NewChain
365365
end || {NewChain, OldChain} <- lists:zip(MapUpdates, Map)],
366-
NewAdjustedMap = maybe_adjust_chain_size(NewMap, BucketConfig),
366+
NewAdjustedMap = case cluster_compat_mode:is_cluster_madhatter() of
367+
true ->
368+
%% Defer adjusting chain length to rebalance, at
369+
%% the time of writing this code the logic is in,
370+
%% ns_rebalancer:do_rebalance_membase_bucket.
371+
NewMap;
372+
false ->
373+
NumReplicas = ns_bucket:num_replicas(BucketConfig),
374+
ns_janitor_map_recoverer:align_replicas(Map,
375+
NumReplicas)
376+
end,
367377
NewBucketConfig = case NewAdjustedMap =:= Map of
368378
true ->
369379
BucketConfig;
@@ -374,10 +384,6 @@ compute_vbucket_map_fixup(Bucket, BucketConfig, States) ->
374384
end,
375385
{NewBucketConfig, IgnoredVBuckets}.
376386

377-
maybe_adjust_chain_size(Map, BucketConfig) ->
378-
NumReplicas = ns_bucket:num_replicas(BucketConfig),
379-
ns_janitor_map_recoverer:align_replicas(Map, NumReplicas).
380-
381387
construct_vbucket_states(VBucket, Chain, States) ->
382388
NodeStates = [{N, S} || {N, V, S} <- States, V == VBucket],
383389
ChainStates = [{N, proplists:get_value(N,
@@ -565,4 +571,29 @@ enumerate_chains_test() ->
565571
EnumeratedChains2 = enumerate_chains(Map, undefined),
566572
[{0, [a, b, c], []}, {1, [b, c, a], []}] = EnumeratedChains2.
567573

574+
sanify_addition_of_replicas_test() ->
575+
[a, b] = do_sanify_chain("B", [{a, 0, active},
576+
{b, 0, replica}],
577+
[a, b], [a, b, c], 0),
578+
[a, b] = do_sanify_chain("B", [{a, 0, active},
579+
{b, 0, replica},
580+
{c, 0, replica}],
581+
[a, b], [a, b, c], 0),
582+
583+
%% replica addition with possible move.
584+
[a, b] = do_sanify_chain("B", [{a, 0, dead},
585+
{b, 0, replica},
586+
{c, 0, pending}],
587+
[a, b], [c, a, b], 0),
588+
[c, d, a] = do_sanify_chain("B", [{a, 0, dead},
589+
{b, 0, replica},
590+
{c, 0, active},
591+
{d, 0, replica}],
592+
[a, b], [c, d, a], 0),
593+
[c, d, a] = do_sanify_chain("B", [{a, 0, replica},
594+
{b, 0, replica},
595+
{c, 0, active},
596+
{d, 0, replica}],
597+
[a, b], [c, d, a], 0).
598+
568599
-endif.

src/ns_rebalancer.erl

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -871,10 +871,21 @@ run_janitor_pre_rebalance(BucketName) ->
871871
do_rebalance_membase_bucket(Bucket, Config,
872872
KeepNodes, ProgressFun, DeltaRecoveryBuckets) ->
873873
Map = proplists:get_value(map, Config),
874+
AdjustedMap = case cluster_compat_mode:is_cluster_madhatter() of
875+
true ->
876+
NumReplicas = ns_bucket:num_replicas(Config),
877+
ns_janitor_map_recoverer:align_replicas(Map,
878+
NumReplicas);
879+
false ->
880+
%% Expect equal length map pre mad-hatter, as the
881+
%% janitor fixes it for us.
882+
%% See fun ns_janitor:compute_vbucket_map_fixup.
883+
Map
884+
end,
874885
{FastForwardMap, MapOptions} =
875886
case lists:keyfind(Bucket, 1, DeltaRecoveryBuckets) of
876887
false ->
877-
generate_vbucket_map(Map, KeepNodes, Config);
888+
generate_vbucket_map(AdjustedMap, KeepNodes, Config);
878889
{_, _, V} ->
879890
V
880891
end,
@@ -1180,7 +1191,8 @@ build_delta_recovery_buckets_loop(MappedConfigs, DeltaRecoveryBuckets, Acc) ->
11801191
[{Bucket, BucketConfig, RecoverResult0} | RestMapped] = MappedConfigs,
11811192

11821193
NeedBucket = lists:member(Bucket, DeltaRecoveryBuckets),
1183-
RecoverResult = case NeedBucket of
1194+
RecoverResult = case NeedBucket andalso
1195+
not ns_bucket:replica_change(BucketConfig) of
11841196
true ->
11851197
RecoverResult0;
11861198
false ->
@@ -1691,17 +1703,21 @@ membase_delta_recovery_buckets_test() ->
16911703
["b1", "b3"] = membase_delta_recovery_buckets(all, MembaseBuckets).
16921704

16931705
build_delta_recovery_buckets_loop_test() ->
1694-
MappedConfigs = [{"b1", conf1, {map, opts}},
1695-
{"b2", conf2, false}],
1706+
%% Fake num_replicas so that we don't crash in
1707+
%% build_delta_recovery_buckets_loop.
1708+
Conf1 = [{num_replicas, 1}, conf1],
1709+
Conf2 = [{num_replicas, 1}, conf2],
1710+
MappedConfigs = [{"b1", Conf1, {map, opts}},
1711+
{"b2", Conf2, false}],
16961712
All = membase_delta_recovery_buckets(all, [{"b1", conf}, {"b2", conf}]),
16971713

16981714
{ok, []} = build_delta_recovery_buckets_loop([], All, []),
16991715
{error, not_possible} = build_delta_recovery_buckets_loop(MappedConfigs, All, []),
17001716
{error, not_possible} = build_delta_recovery_buckets_loop(MappedConfigs, ["b2"], []),
17011717
{error, not_possible} = build_delta_recovery_buckets_loop(MappedConfigs, ["b1", "b2"], []),
17021718
{ok, []} = build_delta_recovery_buckets_loop(MappedConfigs, [], []),
1703-
?assertEqual({ok, [{"b1", conf1, {map, opts}}]},
1719+
?assertEqual({ok, [{"b1", Conf1, {map, opts}}]},
17041720
build_delta_recovery_buckets_loop(MappedConfigs, ["b1"], [])),
1705-
?assertEqual({ok, [{"b1", conf1, {map, opts}}]},
1721+
?assertEqual({ok, [{"b1", Conf1, {map, opts}}]},
17061722
build_delta_recovery_buckets_loop([hd(MappedConfigs)], All, [])).
17071723
-endif.

src/ns_vbucket_mover.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ is_swap_rebalance(OldMap, NewMap) ->
9292
length(OldNodes) =/= length(NewNodes) andalso erlang:throw(not_swap),
9393
lists:foldl(
9494
fun ({_VB, OldChain, NewChain}, Dict0) ->
95+
length(OldChain) =/= length(NewChain) andalso throw(not_swap),
9596
Changed = [Pair || {From, To} = Pair <- lists:zip(OldChain, NewChain),
9697
From =/= To,
9798
From =/= undefined,

0 commit comments

Comments
 (0)