Skip to content
This repository has been archived by the owner on Sep 4, 2019. It is now read-only.

Commit

Permalink
Merge branch 'hb/stdlib/dets_repair/OTP-9622'
Browse files Browse the repository at this point in the history
* hb/stdlib/dets_repair/OTP-9622:
  Fix a minor bug in Dets
  • Loading branch information
uabboli committed Oct 13, 2011
2 parents c3a6ee3 + 30c169c commit 50ea5cd
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 31 deletions.
87 changes: 57 additions & 30 deletions lib/stdlib/src/dets.erl
Expand Up @@ -2475,20 +2475,35 @@ fopen2(Fname, Tab) ->
%% Fd is not always closed upon error, but exit is soon called. %% Fd is not always closed upon error, but exit is soon called.
{ok, Fd, FH} = read_file_header(Fname, Acc, Ram), {ok, Fd, FH} = read_file_header(Fname, Acc, Ram),
Mod = FH#fileheader.mod, Mod = FH#fileheader.mod,
case Mod:check_file_header(FH, Fd) of Do = case Mod:check_file_header(FH, Fd) of
{error, not_closed} -> {ok, Head1, ExtraInfo} ->
io:format(user,"dets: file ~p not properly closed, " Head2 = Head1#head{filename = Fname},
"repairing ...~n", [Fname]), try Mod:init_freelist(Head2, ExtraInfo) of
Ftab ->
{ok, Head1#head{freelists = Ftab}}
catch
throw:_ ->
{repair, " has bad free lists, repairing ..."}
end;
{error, not_closed} ->
M = " not properly closed, repairing ...",
{repair, M};
Else ->
Else
end,
case Do of
{repair, Mess} ->
io:format(user, "dets: file ~p~s~n", [Fname, Mess]),
Version = default, Version = default,
case fsck(Fd, Tab, Fname, FH, default, default, Version) of case fsck(Fd, Tab, Fname, FH, default, default, Version) of
ok -> ok ->
fopen2(Fname, Tab); fopen2(Fname, Tab);
Error -> Error ->
throw(Error) throw(Error)
end; end;
{ok, Head, ExtraInfo} -> {ok, Head} ->
open_final(Head, Fname, Acc, Ram, ?DEFAULT_CACHE, open_final(Head, Fname, Acc, Ram, ?DEFAULT_CACHE,
Tab, ExtraInfo, false); Tab, false);
{error, Reason} -> {error, Reason} ->
throw({error, {Reason, Fname}}) throw({error, {Reason, Fname}})
end; end;
Expand Down Expand Up @@ -2520,12 +2535,13 @@ fopen_existing_file(Tab, OpenArgs) ->
V9 = (Version =:= 9) or (Version =:= default), V9 = (Version =:= 9) or (Version =:= default),
MinF = (MinSlots =:= default) or (MinSlots =:= FH#fileheader.min_no_slots), MinF = (MinSlots =:= default) or (MinSlots =:= FH#fileheader.min_no_slots),
MaxF = (MaxSlots =:= default) or (MaxSlots =:= FH#fileheader.max_no_slots), MaxF = (MaxSlots =:= default) or (MaxSlots =:= FH#fileheader.max_no_slots),
Do = case (FH#fileheader.mod):check_file_header(FH, Fd) of Mod = (FH#fileheader.mod),
Wh = case Mod:check_file_header(FH, Fd) of
{ok, Head, true} when Rep =:= force, Acc =:= read_write, {ok, Head, true} when Rep =:= force, Acc =:= read_write,
FH#fileheader.version =:= 9, FH#fileheader.version =:= 9,
FH#fileheader.no_colls =/= undefined, FH#fileheader.no_colls =/= undefined,
MinF, MaxF, V9 -> MinF, MaxF, V9 ->
{compact, Head}; {compact, Head, true};
{ok, _Head, _Extra} when Rep =:= force, Acc =:= read -> {ok, _Head, _Extra} when Rep =:= force, Acc =:= read ->
throw({error, {access_mode, Fname}}); throw({error, {access_mode, Fname}});
{ok, Head, need_compacting} when Acc =:= read -> {ok, Head, need_compacting} when Acc =:= read ->
Expand Down Expand Up @@ -2555,6 +2571,19 @@ fopen_existing_file(Tab, OpenArgs) ->
{error, Reason} -> {error, Reason} ->
throw({error, {Reason, Fname}}) throw({error, {Reason, Fname}})
end, end,
Do = case Wh of
{Tag, Hd, Extra} when Tag =:= final; Tag =:= compact ->
Hd1 = Hd#head{filename = Fname},
try Mod:init_freelist(Hd1, Extra) of
Ftab ->
{Tag, Hd#head{freelists = Ftab}}
catch
throw:_ ->
{repair, " has bad free lists, repairing ..."}
end;
Else ->
Else
end,
case Do of case Do of
_ when FH#fileheader.type =/= Type -> _ when FH#fileheader.type =/= Type ->
throw({error, {type_mismatch, Fname}}); throw({error, {type_mismatch, Fname}});
Expand All @@ -2563,8 +2592,7 @@ fopen_existing_file(Tab, OpenArgs) ->
{compact, SourceHead} -> {compact, SourceHead} ->
io:format(user, "dets: file ~p is now compacted ...~n", [Fname]), io:format(user, "dets: file ~p is now compacted ...~n", [Fname]),
{ok, NewSourceHead} = open_final(SourceHead, Fname, read, false, {ok, NewSourceHead} = open_final(SourceHead, Fname, read, false,
?DEFAULT_CACHE, Tab, true, ?DEFAULT_CACHE, Tab, Debug),
Debug),
case catch compact(NewSourceHead) of case catch compact(NewSourceHead) of
ok -> ok ->
erlang:garbage_collect(), erlang:garbage_collect(),
Expand All @@ -2584,9 +2612,9 @@ fopen_existing_file(Tab, OpenArgs) ->
Version, OpenArgs); Version, OpenArgs);
_ when FH#fileheader.version =/= Version, Version =/= default -> _ when FH#fileheader.version =/= Version, Version =/= default ->
throw({error, {version_mismatch, Fname}}); throw({error, {version_mismatch, Fname}});
{final, H, EI} -> {final, H} ->
H1 = H#head{auto_save = Auto}, H1 = H#head{auto_save = Auto},
open_final(H1, Fname, Acc, Ram, CacheSz, Tab, EI, Debug) open_final(H1, Fname, Acc, Ram, CacheSz, Tab, Debug)
end. end.


do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) -> do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) ->
Expand All @@ -2600,19 +2628,16 @@ do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) ->
end. end.


%% -> {ok, head()} | throw(Error) %% -> {ok, head()} | throw(Error)
open_final(Head, Fname, Acc, Ram, CacheSz, Tab, ExtraInfo, Debug) -> open_final(Head, Fname, Acc, Ram, CacheSz, Tab, Debug) ->
Head1 = Head#head{access = Acc, Head1 = Head#head{access = Acc,
ram_file = Ram, ram_file = Ram,
filename = Fname, filename = Fname,
name = Tab, name = Tab,
cache = dets_utils:new_cache(CacheSz)}, cache = dets_utils:new_cache(CacheSz)},
init_disk_map(Head1#head.version, Tab, Debug), init_disk_map(Head1#head.version, Tab, Debug),
Mod = Head#head.mod, (Head1#head.mod):cache_segps(Head1#head.fptr, Fname, Head1#head.next),
Mod:cache_segps(Head1#head.fptr, Fname, Head1#head.next),
Ftab = Mod:init_freelist(Head1, ExtraInfo),
check_growth(Head1), check_growth(Head1),
NewHead = Head1#head{freelists = Ftab}, {ok, Head1}.
{ok, NewHead}.


%% -> {ok, head()} | throw(Error) %% -> {ok, head()} | throw(Error)
fopen_init_file(Tab, OpenArgs) -> fopen_init_file(Tab, OpenArgs) ->
Expand Down Expand Up @@ -3241,18 +3266,20 @@ view(FileName) ->
case catch read_file_header(FileName, read, false) of case catch read_file_header(FileName, read, false) of
{ok, Fd, FH} -> {ok, Fd, FH} ->
Mod = FH#fileheader.mod, Mod = FH#fileheader.mod,
case Mod:check_file_header(FH, Fd) of try
{ok, H0, ExtraInfo} -> case Mod:check_file_header(FH, Fd) of
Ftab = Mod:init_freelist(H0, ExtraInfo), {ok, H0, ExtraInfo} ->
{_Bump, Base} = constants(FH, FileName), Ftab = Mod:init_freelist(H0, ExtraInfo),
H = H0#head{freelists=Ftab, base = Base}, {_Bump, Base} = constants(FH, FileName),
v_free_list(H), H = H0#head{freelists=Ftab, base = Base},
Mod:v_segments(H), v_free_list(H),
file:close(Fd); Mod:v_segments(H),
X -> ok;
file:close(Fd), X ->
X X
end; end
after file:close(Fd)
end;
X -> X ->
X X
end. end.
Expand Down
4 changes: 3 additions & 1 deletion lib/stdlib/test/dets_SUITE.erl
Expand Up @@ -1568,8 +1568,10 @@ repair(Config, V) ->
?line FileSize = dets:info(TabRef, memory), ?line FileSize = dets:info(TabRef, memory),
?line ok = dets:close(TabRef), ?line ok = dets:close(TabRef),
crash(Fname, FileSize+20), crash(Fname, FileSize+20),
?line {error, {bad_freelists, Fname}} = %% Used to return bad_freelists, but that changed in OTP-9622
?line {ok, TabRef} =
dets:open_file(TabRef, [{file,Fname},{version,V}]), dets:open_file(TabRef, [{file,Fname},{version,V}]),
?line ok = dets:close(TabRef),
?line file:delete(Fname), ?line file:delete(Fname),


%% File not closed, opening with read and read_write access tried. %% File not closed, opening with read and read_write access tried.
Expand Down

0 comments on commit 50ea5cd

Please sign in to comment.