Skip to content

Commit 013b1c5

Browse files
committed
Merge pull request #709 from basho/bugfix/cs-filter-block-tombstone
Separate configs and defaults between fs/rt for Riak CS block tombstone filter [JIRA: RIAK-2215] Reviewed-by: kuenishi
2 parents e33d488 + c00ae7e commit 013b1c5

File tree

2 files changed

+72
-12
lines changed

2 files changed

+72
-12
lines changed

src/riak_repl_cs.erl

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
-define(BUCKETS_BUCKET, <<"moss.buckets">>).
3333

3434
-define(CONFIG_REPL_BLOCKS, replicate_cs_blocks_realtime).
35-
-define(CONFIG_REPL_BLOCK_TOMBSTONE, replicate_cs_block_tombstone).
35+
-define(CONFIG_REPL_BLOCK_TOMBSTONE_RT, replicate_cs_block_tombstone_realtime).
36+
-define(CONFIG_REPL_BLOCK_TOMBSTONE_FS, replicate_cs_block_tombstone_fullsync).
3637
-define(CONFIG_REPL_USERS, replicate_cs_user_objects).
3738
-define(CONFIG_REPL_BUCKETS, replicate_cs_bucket_objects).
3839

@@ -69,8 +70,19 @@ replicate_object(<<?BLOCK_BUCKET_PREFIX, _Rest/binary>>, IsTombstone, FSorRT) ->
6970
true;
7071
{false, realtime} ->
7172
app_helper:get_env(riak_repl, ?CONFIG_REPL_BLOCKS, false);
72-
{true, _} ->
73-
app_helper:get_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE, true)
73+
{true, fullsync} ->
74+
%% Default for tombstoned blocks is *NO PROPAGATE*.
75+
%% Tombstoned blocks at fullsync are probably lingering ones.
76+
%% Propagating them to sink will trigger putting tombstones and
77+
%% reaping them almost in vein. Coming fullsyncs will again propagate
78+
%% them again and again.
79+
app_helper:get_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE_FS, false);
80+
{true, realtime} ->
81+
%% Default for tombstoned blocks is GO AHEAD.
82+
%% Tombstons put at sink side carry information about overwrite
83+
%% by its vclock, it enables that sink avoid read phase of
84+
%% read-before-delete and eases disk load caused by read.
85+
app_helper:get_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE_RT, true)
7486
end;
7587
replicate_object(_, true, _) -> false;
7688
replicate_object(?STORAGE_BUCKET, _, _) -> false;
@@ -95,7 +107,8 @@ bool_to_ok_or_cancel(false) ->
95107

96108
reset_app_env() ->
97109
ok = application:unset_env(riak_repl, ?CONFIG_REPL_BLOCKS),
98-
ok = application:unset_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE),
110+
ok = application:unset_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE_RT),
111+
ok = application:unset_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE_FS),
99112
ok = application:unset_env(riak_repl, ?CONFIG_REPL_USERS),
100113
ok = application:unset_env(riak_repl, ?CONFIG_REPL_BUCKETS).
101114

@@ -128,17 +141,42 @@ dont_repl_storage_objects_test() ->
128141

129142
dont_repl_tombstoned_object_test() ->
130143
reset_app_env(),
131-
ok = application:set_env(riak_repl, replicate_cs_block_tombstone, false),
132144
%% the riak client isn't even used
133145
Client = fake_client,
134-
Bucket = <<"anything">>,
146+
Bucket = <<"almost_anything">>,
135147
Object = riak_object:new(Bucket, <<"key">>, <<"val">>),
136148
M = dict:from_list([{<<"X-Riak-Deleted">>, true}]),
137149
Object2 = riak_object:update_metadata(Object, M),
138150
Object3 = riak_object:apply_updates(Object2),
139151
?assertNot(ok_or_cancel_to_bool(send(Object3, Client))),
140152
?assertNot(ok_or_cancel_to_bool(send_realtime(Object3, Client))).
141153

154+
repl_block_tombstone_by_default_test() ->
155+
reset_app_env(),
156+
%% the riak client isn't even used
157+
Client = fake_client,
158+
Bucket = <<"0b:HASHEDUP">>,
159+
Object = riak_object:new(Bucket, <<"key">>, <<"val">>),
160+
M = dict:from_list([{<<"X-Riak-Deleted">>, true}]),
161+
Object2 = riak_object:update_metadata(Object, M),
162+
Object3 = riak_object:apply_updates(Object2),
163+
?assertNot(ok_or_cancel_to_bool(send(Object3, Client))),
164+
?assert(ok_or_cancel_to_bool(send_realtime(Object3, Client))).
165+
166+
repl_block_tombstone_customized_test() ->
167+
reset_app_env(),
168+
ok = application:set_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE_RT, false),
169+
ok = application:set_env(riak_repl, ?CONFIG_REPL_BLOCK_TOMBSTONE_FS, true),
170+
%% the riak client isn't even used
171+
Client = fake_client,
172+
Bucket = <<"0b:HASHEDUP">>,
173+
Object = riak_object:new(Bucket, <<"key">>, <<"val">>),
174+
M = dict:from_list([{<<"X-Riak-Deleted">>, true}]),
175+
Object2 = riak_object:update_metadata(Object, M),
176+
Object3 = riak_object:apply_updates(Object2),
177+
?assert(ok_or_cancel_to_bool(send(Object3, Client))),
178+
?assertNot(ok_or_cancel_to_bool(send_realtime(Object3, Client))).
179+
142180
repl_user_object_test() ->
143181
reset_app_env(),
144182
%% the riak client isn't even used

test/riak_repl_cs_eqc.erl

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ decision_table_v2() ->
3535
[{buckets, ok, ok}, %% Configurable, but default
3636
{users, ok, ok}, %% Configurable, but default
3737
{blocks, cancel, ok},
38-
{block_ts, ok, ok},
38+
{block_ts, ok, cancel},
3939
{manifests, ok, ok},
4040
{gc, ok, ok}, %% riak-cs-gc
4141
{access, cancel, cancel},
@@ -49,7 +49,21 @@ decision_table_v2_blockrt() ->
4949
[{buckets, ok, ok}, %% Configurable, but default
5050
{users, ok, ok}, %% Configurable, but default
5151
{blocks, ok, ok},
52-
{block_ts, ok, ok},
52+
{block_ts, ok, cancel},
53+
{manifests, ok, ok},
54+
{gc, ok, ok}, %% riak-cs-gc
55+
{access, cancel, cancel},
56+
{storage, cancel, cancel},
57+
{mb, ok, ok}, %% Multibag
58+
{tss, cancel, cancel}, %% Tombstones in short
59+
{other, ok, ok}].
60+
61+
decision_table_v2_no_blockts_rt() ->
62+
%% type, rt, fs
63+
[{buckets, ok, ok}, %% Configurable, but default
64+
{users, ok, ok}, %% Configurable, but default
65+
{blocks, cancel, ok},
66+
{block_ts, cancel, cancel},
5367
{manifests, ok, ok},
5468
{gc, ok, ok}, %% riak-cs-gc
5569
{access, cancel, cancel},
@@ -116,20 +130,22 @@ eqc_test_() ->
116130
[ % run qc tests
117131
?_assertEqual(true, eqc:quickcheck(eqc:numtests(NumTests, ?QC_OUT(prop_main(v1))))),
118132
?_assertEqual(true, eqc:quickcheck(eqc:numtests(NumTests, ?QC_OUT(prop_main(v2))))),
119-
?_assertEqual(true, eqc:quickcheck(eqc:numtests(NumTests, ?QC_OUT(prop_main(v2_blockrt)))))
133+
?_assertEqual(true, eqc:quickcheck(eqc:numtests(NumTests, ?QC_OUT(prop_main(v2_blockrt))))),
134+
?_assertEqual(true, eqc:quickcheck(eqc:numtests(NumTests, ?QC_OUT(prop_main(v2_no_blockts_rt)))))
120135
]}.
121136

122137
fs_or_rt() -> oneof([fs, rt]).
123138

124139
prop_main(DecisionTableVersion) ->
125-
ok = application:unset_env(riak_repl, replicate_cs_block_tombstone),
140+
ok = application:unset_env(riak_repl, replicate_cs_block_tombstone_realtime),
141+
ok = application:unset_env(riak_repl, replicate_cs_block_tombstone_fullsync),
126142
ok = application:unset_env(riak_repl, replicate_cs_blocks_realtime),
127143
DecisionTable
128144
= case DecisionTableVersion of
129145
v1 ->
130146
%% Default behaviour in Riak EE 1.4~2.1.1
131147
ok = application:set_env(riak_repl,
132-
replicate_cs_block_tombstone,
148+
replicate_cs_block_tombstone_realtime,
133149
false),
134150
decision_table();
135151
v2 ->
@@ -140,7 +156,13 @@ prop_main(DecisionTableVersion) ->
140156
ok = application:set_env(riak_repl,
141157
replicate_cs_blocks_realtime,
142158
true),
143-
decision_table_v2_blockrt()
159+
decision_table_v2_blockrt();
160+
v2_no_blockts_rt ->
161+
%% Prevent block tombstone propagation in realtime, on by default
162+
ok = application:set_env(riak_repl,
163+
replicate_cs_block_tombstone_realtime,
164+
false),
165+
decision_table_v2_no_blockts_rt()
144166
end,
145167
?FORALL({Object, FSorRT}, {riak_object(), fs_or_rt()},
146168
begin

0 commit comments

Comments
 (0)