-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FML: fix tombstone merging bug when K & K's tombstone are in same fileid
Originally found with bitcask_pulse, I deconstructed the test case to help understand what was happening: the new EUnit test is new_20131217_a_test_. As a result of the puts, key #13 is written 3x to fileid #1 (normal, tombstone, normal) and 1x to fileid #2 (normal @ the very beginning of the file). The merge creates fileid #3 and copies only the tombstone (the normal entry isn't copied because it is out-of-date). Before the close, the internal keydir contains the correct info about key #13, but after the close and re-open, we see key #13's entries: normal (and most recent) in fileid 32, and tombstone in fileid #3, oops. The fix is to remove all of the merge input fileids from the set of fileids that will survive/exist after the merge is finished.
- Loading branch information
1 parent
afc5c3f
commit 1712650
Showing
3 changed files
with
138 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
-module(foo). | ||
-compile(export_all). | ||
|
||
-define(FILE_SIZE, 1000). | ||
-define(BITCASK, "test-bitcask-dir"). | ||
|
||
t() -> | ||
os:cmd("rm -rf " ++ ?BITCASK), | ||
BC = bc_open(true), | ||
puts(BC, {1,22},<<>>), | ||
puts(BC, {1,11},<<0>>), | ||
puts(BC,{1,22},<<>>), | ||
spawn(fun() -> fork_merge(BC), io:format("fork_merge done!\n") end), | ||
timer:sleep(1000), | ||
io:format("t pid ~p is done\n", [self()]). | ||
|
||
bc_open(Writer) -> | ||
case Writer of | ||
true -> catch bitcask:open(?BITCASK, [read_write, {max_file_size, ?FILE_SIZE}, {open_timeout, 1234}]); | ||
false -> catch bitcask:open(?BITCASK, [{open_timeout, 1234}]) | ||
end. | ||
|
||
puts(H, {K1, K2}, V) -> | ||
case lists:usort([ put(H, K, V) || K <- lists:seq(K1, K2) ]) of | ||
[ok] -> ok; | ||
Other -> Other | ||
end. | ||
|
||
put(H, K, V) -> | ||
ok = bitcask:put(H, <<K:32>>, V). | ||
|
||
fork_merge(H) -> | ||
case bitcask:needs_merge(H) of | ||
{true, Files} -> catch io:format("Yo, gonna merge!\n"), bitcask_merge_worker:merge(?BITCASK, [], Files); | ||
false -> not_needed | ||
end. | ||
|