Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add initial vclock to per node keys that changed since 1.6.5.

This change fixes MB-4219.

When config merging routines encounter two values not having vclocks
attached to them then the value that came from remote node is
chosen. This can cause certain races. Particularly this is the cause
of upgrade issues seen on windows: when node is started for the first
time it upgrades old config but then it pulls the config from other
nodes and prefers foreign value (outdated one) to its own. This change
introduces initial vclocks for such vulnerable keys so that new values
will be preferred.

Change-Id: Ibe85213eb8df2392f6b4b34413062c0aed19c0a1
Reviewed-on: http://review.couchbase.org/9206
Reviewed-by: Aliaksey Kandratsenka <alkondratenko@gmail.com>
Tested-by: Aliaksey Kandratsenka <alkondratenko@gmail.com>
  • Loading branch information...
commit 850003232fb2bc2ec1a7cc8862419a28cda4b456 1 parent 02ef5f3
Aliaksey Artamonau aartamonau authored alk committed

Showing 1 changed file with 46 additions and 5 deletions. Show diff stats Hide diff stats

  1. +46 5 src/ns_config_default.erl
51 src/ns_config_default.erl
@@ -16,6 +16,7 @@
16 16 -module(ns_config_default).
17 17
18 18 -include("ns_common.hrl").
  19 +-include("ns_config.hrl").
19 20
20 21 -include_lib("eunit/include/eunit.hrl").
21 22
@@ -225,10 +226,22 @@ do_upgrade_config_from_1_6_to_1_7(Config, DefaultConfig) ->
225 226 lists:keyreplace(element(1, T), 1, Acc, T)
226 227 end, MemcachedCfg, [BucketEnCfg,
227 228 EnginesCfg]),
228   - [{set, {node, node(), memcached}, NewMemcachedCfg}] ++
  229 +
  230 + VClock = vclock:increment(node(), vclock:fresh()),
  231 + AddVClock = fun (Value) ->
  232 + [{?METADATA_VCLOCK, VClock} | Value]
  233 + end,
  234 +
  235 + [{set, {node, node(), memcached}, AddVClock(NewMemcachedCfg)}] ++
229 236 lists:foldl(fun (K, Acc) ->
230 237 {K,V} = lists:keyfind(K, 1, DefaultConfig),
231   - [{set, K, V} | Acc]
  238 + V1 = case K of
  239 + {node, Node, _K} when node() =:= Node ->
  240 + AddVClock(V);
  241 + _Otherwise ->
  242 + V
  243 + end,
  244 + [{set, K, V1} | Acc]
232 245 end, [],
233 246 [directory,
234 247 {node, node(), isasl},
@@ -261,9 +274,27 @@ upgrade_1_6_to_1_7_test() ->
261 274 [{dbdir, "dbdir"},
262 275 {bucket_engine, "old-be"},
263 276 {engines, "old-engines"}]}],
  277 +
  278 + StripValue = fun ([{?METADATA_VCLOCK, _V} | Rest]) ->
  279 + Rest;
  280 + (Other) ->
  281 + Other
  282 + end,
  283 + Strip = fun (Config) ->
  284 + lists:map(
  285 + fun ({set, K, V}) ->
  286 + {set, K, StripValue(V)};
  287 + (Other) ->
  288 + Other
  289 + end,
  290 + Config)
  291 + end,
  292 +
264 293 Res = do_upgrade_config_from_1_6_to_1_7([OldCfg], DefaultCfg),
  294 +
265 295 ?assertEqual(lists:sort([{set, directory, default_directory},
266   - {set, {node, node(), isasl}, [{path, default_isasl}]},
  296 + {set, {node, node(), isasl},
  297 + [{path, default_isasl}]},
267 298 {set, {node, node(), memcached},
268 299 [{dbdir, "dbdir"},
269 300 {bucket_engine, "new-be"},
@@ -272,7 +303,7 @@ upgrade_1_6_to_1_7_test() ->
272 303 [{moxi, "moxi something"},
273 304 {memcached, "memcached something"}]},
274 305 {set, {node, node(), ns_log}, default_log}]),
275   - lists:sort(Res)).
  306 + lists:sort(Strip(Res))).
276 307
277 308 no_upgrade_on_1_7_1_test() ->
278 309 ?assertEqual([], upgrade_config([[{{node, node(), config_version}, {1,7,1}}]])).
@@ -309,5 +340,15 @@ fuller_1_6_test_() ->
309 340 [X || {set, directory, _} = X <- Changes]),
310 341
311 342 {set, _, NewMemcached} = lists:keyfind({node, node(), memcached}, 2, Changes),
312   - ?assertEqual({dbdir, "dbdir"}, lists:keyfind(dbdir, 1, NewMemcached))
  343 + ?assertEqual({dbdir, "dbdir"}, lists:keyfind(dbdir, 1, NewMemcached)),
  344 +
  345 + ?assertMatch({set, {node, Node, memcached},
  346 + [{?METADATA_VCLOCK, _VClock} | _]} when Node =:= node(),
  347 + lists:keyfind({node, node(), memcached}, 2, Changes)),
  348 + ?assertMatch({set, {node, Node, isasl},
  349 + [{?METADATA_VCLOCK, _VClock} | _]} when Node =:= node(),
  350 + lists:keyfind({node, node(), isasl}, 2, Changes)),
  351 + ?assertMatch({set, {node, Node, ns_log},
  352 + [{?METADATA_VCLOCK, _VClock} | _]} when Node =:= node(),
  353 + lists:keyfind({node, node(), ns_log}, 2, Changes))
313 354 end}.

0 comments on commit 8500032

Please sign in to comment.
Something went wrong with that request. Please try again.