Skip to content

Commit 5d9989f

Browse files
committed
Merge pull request #189 from basho/bugfix/list-dir-port-refresh
Refresh efile port if gone Reviewed-by: slfritchie
2 parents 94e0857 + f947c2c commit 5d9989f

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/bitcask.erl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,6 +2870,25 @@ corrupt_file(Path, Offset, Data) ->
28702870
ok = file:write(FH, Data),
28712871
file:close(FH).
28722872

2873+
% Verify that if the cached efile port goes away, we can recover
2874+
% and not get stuck opening casks
2875+
efile_error_test() ->
2876+
Dir = "/tmp/bc.efile.error",
2877+
B = bitcask:open(Dir, [read_write]),
2878+
ok = bitcask:put(B, <<"k">>, <<"v">>),
2879+
ok = bitcask:close(B),
2880+
Port = get(bitcask_efile_port),
2881+
% If this fails, we stopped using the efile port trick to list
2882+
% dir contents, so remove this test
2883+
?assert(is_port(Port)),
2884+
true = erlang:port_close(Port),
2885+
case bitcask:open(Dir) of
2886+
{error, _} = Err ->
2887+
?assertEqual(ok, Err);
2888+
B2 when is_reference(B2) ->
2889+
ok = bitcask:close(B2)
2890+
end.
2891+
28732892
%% About leak_t0():
28742893
%%
28752894
%% If bitcask leaks file descriptors for the 'touch'ed files, output is:

src/bitcask_fileops.erl

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060
-include_lib("eqc/include/eqc_fsm.hrl").
6161
-endif.
6262
-compile(export_all).
63-
-endif.
6463
-include_lib("eunit/include/eunit.hrl").
64+
-endif.
6565

6666
%% @doc Open a new file for writing.
6767
%% Called on a Dirname, will open a fresh file in that directory.
@@ -854,9 +854,20 @@ ensure_dir(F) ->
854854
end
855855
end.
856856

857-
list_dir(Directory) ->
857+
list_dir(Dir) ->
858+
list_dir(Dir, 1).
859+
860+
list_dir(_, 0) ->
861+
{error, efile_driver_unavailable};
862+
list_dir(Directory, Retries) when is_integer(Retries), Retries > 0 ->
858863
Port = get_efile_port(),
859-
prim_file:list_dir(Port, Directory).
864+
case prim_file:list_dir(Port, Directory) of
865+
{error, einval} ->
866+
clear_efile_port(),
867+
list_dir(Directory, Retries-1);
868+
Result ->
869+
Result
870+
end.
860871

861872
get_efile_port() ->
862873
Key = bitcask_efile_port,
@@ -875,6 +886,9 @@ get_efile_port() ->
875886
Port
876887
end.
877888

889+
clear_efile_port() ->
890+
erase(bitcask_efile_port).
891+
878892
prim_file_drv_open(Driver, Portopts) ->
879893
try erlang:open_port({spawn, Driver}, Portopts) of
880894
Port ->

0 commit comments

Comments
 (0)