diff --git a/src/bitcask.erl b/src/bitcask.erl index e62d534b..ef794b74 100644 --- a/src/bitcask.erl +++ b/src/bitcask.erl @@ -1729,15 +1729,21 @@ do_put(Key, Value, #bc_state{write_file = WriteFile} = State, State3 = wrap_write_file(State2), do_put(Key, Value, State3, Retries - 1, already_exists); - #bitcask_entry{file_id=OldFileId,offset=OldOffset} - when OldFileId =< WriteFileId -> - PrevTombstone = <>, - {ok, WriteFile1, _, _} = - bitcask_fileops:write(WriteFile0, Key, PrevTombstone, - Tstamp), - State3 = State2#bc_state{write_file = WriteFile1}, + #bitcask_entry{file_id=OldFileId,offset=OldOffset} -> + State3 = + case OldFileId < WriteFileId of + true -> + PrevTomb = <>, + {ok, WriteFile1, _, _} = + bitcask_fileops:write(WriteFile0, Key, + PrevTomb, Tstamp), + State2#bc_state{write_file = WriteFile1}; + false -> + State2 + end, write_and_keydir_put(State3, Key, Value, Tstamp, Retries, bitcask_time:tstamp(), OldFileId, OldOffset); + _ -> State3 = State2#bc_state{write_file = WriteFile0}, write_and_keydir_put(State3, Key, Value, Tstamp, Retries, @@ -3439,6 +3445,31 @@ legacy_tombstones_test2() -> bitcask:close(B), ?assertEqual([Last], AllFiles3). +update_tombstones_test() -> + Dir = "/tmp/bc.update.tombstones", + Key = <<"k">>, + Data = [{Key, integer_to_binary(N)} || N <- lists:seq(1, 10)], + B = init_dataset(Dir, [read_write, {max_file_size, 50000000}], Data), + ok = bitcask:close(B), + % Re-open to guarantee opening a second file. + % An update on the new file requires a tombstone. + B2 = bitcask:open(Dir, [read_write, {max_file_size, 50000000}]), + ok = bitcask:put(B2, Key, <<"last_val">>), + ok = bitcask:close(B2), + Files = bitcask:readable_files(Dir), + Fds = [begin + {ok, Fd} = bitcask_fileops:open_file(File), + Fd + end || File <- Files], + CountF = fun(_K, V, _Tstamp, _, Acc) -> + case bitcask:is_tombstone(V) of + true -> Acc + 1; + false -> Acc + end + end, + TombCount = bitcask:subfold(CountF, Fds, 0), + ?assertEqual(1, TombCount). + make_merge_file(Dir, Seed, Probability) -> random:seed(Seed), case filelib:is_dir(Dir) of