aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mnesia
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mnesia')
-rw-r--r--lib/mnesia/doc/src/mnesia.xml6
-rw-r--r--lib/mnesia/src/mnesia.app.src2
-rw-r--r--lib/mnesia/src/mnesia.erl62
-rw-r--r--lib/mnesia/src/mnesia.hrl11
-rw-r--r--lib/mnesia/src/mnesia_bup.erl229
-rw-r--r--lib/mnesia/src/mnesia_checkpoint.erl40
-rw-r--r--lib/mnesia/src/mnesia_controller.erl77
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl157
-rw-r--r--lib/mnesia/src/mnesia_event.erl3
-rw-r--r--lib/mnesia/src/mnesia_frag.erl59
-rw-r--r--lib/mnesia/src/mnesia_index.erl12
-rw-r--r--lib/mnesia/src/mnesia_late_loader.erl6
-rw-r--r--lib/mnesia/src/mnesia_lib.erl136
-rw-r--r--lib/mnesia/src/mnesia_loader.erl71
-rw-r--r--lib/mnesia/src/mnesia_locker.erl19
-rw-r--r--lib/mnesia/src/mnesia_log.erl46
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl42
-rw-r--r--lib/mnesia/src/mnesia_recover.erl36
-rw-r--r--lib/mnesia/src/mnesia_schema.erl49
-rw-r--r--lib/mnesia/src/mnesia_snmp_hook.erl17
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl33
-rw-r--r--lib/mnesia/src/mnesia_text.erl22
-rw-r--r--lib/mnesia/src/mnesia_tm.erl196
-rw-r--r--lib/mnesia/test/mnesia_config_backup.erl3
-rw-r--r--lib/mnesia/test/mnesia_config_test.erl22
-rw-r--r--lib/mnesia/test/mnesia_evil_backup.erl19
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl6
-rw-r--r--lib/mnesia/test/mnesia_trans_access_test.erl6
-rw-r--r--lib/mnesia/vsn.mk2
29 files changed, 671 insertions, 718 deletions
diff --git a/lib/mnesia/doc/src/mnesia.xml b/lib/mnesia/doc/src/mnesia.xml
index ed5b879f7f..856a7594a7 100644
--- a/lib/mnesia/doc/src/mnesia.xml
+++ b/lib/mnesia/doc/src/mnesia.xml
@@ -3019,6 +3019,12 @@ raise(Name, Amount) ->
totally unpredictable.</p>
</item>
<item>
+ <p><c>-mnesia dump_disc_copies_at_startup true | false</c>.
+ If set to false, this disables the dumping of <c>disc_copies</c>
+ tables during startup while tables are being loaded. The default
+ is true.</p>
+ </item>
+ <item>
<p><c>-mnesia dump_log_load_regulation true | false</c>.
Controls if the log dumps should be performed as fast as
possible or if the dumper should do its own load
diff --git a/lib/mnesia/src/mnesia.app.src b/lib/mnesia/src/mnesia.app.src
index e755864792..c78a7cba1e 100644
--- a/lib/mnesia/src/mnesia.app.src
+++ b/lib/mnesia/src/mnesia.app.src
@@ -48,6 +48,6 @@
]},
{applications, [kernel, stdlib]},
{mod, {mnesia_sup, []}},
- {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-6.0"]}]}.
+ {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-7.0"]}]}.
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 8f14831ad3..b9c2fd915c 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -145,7 +145,7 @@
%% Local function in order to avoid external function call
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
Value -> Value
end.
@@ -306,6 +306,8 @@ ms() ->
-spec abort(_) -> no_return().
+abort(Reason = {aborted, _}) ->
+ exit(Reason);
abort(Reason) ->
exit({aborted, Reason}).
@@ -807,7 +809,7 @@ next(Tid,Ts,Tab,Key)
tid ->
lock_table(Tid, Ts, Tab, read),
do_fixtable(Tab,Ts),
- New = (catch dirty_next(Tab,Key)),
+ New = ?CATCH(dirty_next(Tab,Key)),
stored_keys(Tab,New,Key,Ts,next,
val({Tab, setorbag}));
_Protocol ->
@@ -833,7 +835,7 @@ prev(Tid,Ts,Tab,Key)
tid ->
lock_table(Tid, Ts, Tab, read),
do_fixtable(Tab,Ts),
- New = (catch dirty_prev(Tab,Key)),
+ New = ?CATCH(dirty_prev(Tab,Key)),
stored_keys(Tab,New,Key,Ts,prev,
val({Tab, setorbag}));
_Protocol ->
@@ -965,7 +967,7 @@ foldl(Fun, Acc, Tab, LockKind) when is_function(Fun) ->
foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
{Type, Prev} = init_iteration(ActivityId, Opaque, Tab, LockKind),
- Res = (catch do_foldl(ActivityId, Opaque, Tab, dirty_first(Tab), Fun, Acc, Type, Prev)),
+ Res = ?CATCH(do_foldl(ActivityId, Opaque, Tab, dirty_first(Tab), Fun, Acc, Type, Prev)),
close_iteration(Res, Tab).
do_foldl(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
@@ -1011,7 +1013,7 @@ foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
true -> %% Order doesn't matter for set and bag
TempPrev %% Keep the order so we can use ordsets:del_element
end,
- Res = (catch do_foldr(ActivityId, Opaque, Tab, dirty_last(Tab), Fun, Acc, Type, Prev)),
+ Res = ?CATCH(do_foldr(ActivityId, Opaque, Tab, dirty_last(Tab), Fun, Acc, Type, Prev)),
close_iteration(Res, Tab).
do_foldr(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
@@ -1626,13 +1628,7 @@ dirty_read(Oid) ->
dirty_read(Tab, Key)
when is_atom(Tab), Tab /= schema ->
-%% case catch ?ets_lookup(Tab, Key) of
-%% {'EXIT', _} ->
- %% Bad luck, we have to perform a real lookup
- dirty_rpc(Tab, mnesia_lib, db_get, [Tab, Key]);
-%% Val ->
-%% Val
-%% end;
+ dirty_rpc(Tab, mnesia_lib, db_get, [Tab, Key]);
dirty_read(Tab, _Key) ->
abort({bad_type, Tab}).
@@ -1905,21 +1901,21 @@ any_table_info(Tab, _Item) ->
abort({bad_type, Tab}).
raw_table_info(Tab, Item) ->
- case ?catch_val({Tab, storage_type}) of
- ram_copies ->
- info_reply(catch ?ets_info(Tab, Item), Tab, Item);
- disc_copies ->
- info_reply(catch ?ets_info(Tab, Item), Tab, Item);
- disc_only_copies ->
- info_reply(catch dets:info(Tab, Item), Tab, Item);
- unknown ->
- bad_info_reply(Tab, Item);
- {'EXIT', _} ->
+ try
+ case ?ets_lookup_element(mnesia_gvar, {Tab, storage_type}, 2) of
+ ram_copies ->
+ info_reply(?ets_info(Tab, Item), Tab, Item);
+ disc_copies ->
+ info_reply(?ets_info(Tab, Item), Tab, Item);
+ disc_only_copies ->
+ info_reply(dets:info(Tab, Item), Tab, Item);
+ unknown ->
+ bad_info_reply(Tab, Item)
+ end
+ catch error:_ ->
bad_info_reply(Tab, Item)
end.
-info_reply({'EXIT', _Reason}, Tab, Item) ->
- bad_info_reply(Tab, Item);
info_reply({error, _Reason}, Tab, Item) ->
bad_info_reply(Tab, Item);
info_reply(Val, _Tab, _Item) ->
@@ -2063,9 +2059,8 @@ storage_count(T, {U, R, D, DO}) ->
end.
system_info(Item) ->
- case catch system_info2(Item) of
- {'EXIT',Error} -> abort(Error);
- Other -> Other
+ try system_info2(Item)
+ catch _:Error -> abort(Error)
end.
system_info2(all) ->
@@ -2171,7 +2166,7 @@ system_info2(version) ->
Version;
false ->
%% Ensure that it does not match
- {mnesia_not_loaded, node(), now()}
+ {mnesia_not_loaded, node(), erlang:timestamp()}
end;
Version ->
Version
@@ -2381,11 +2376,10 @@ del_table_index(Tab, Ix) ->
mnesia_schema:del_table_index(Tab, Ix).
transform_table(Tab, Fun, NewA) ->
- case catch val({Tab, record_name}) of
- {'EXIT', Reason} ->
- mnesia:abort(Reason);
- OldRN ->
- mnesia_schema:transform_table(Tab, Fun, NewA, OldRN)
+ try val({Tab, record_name}) of
+ OldRN -> mnesia_schema:transform_table(Tab, Fun, NewA, OldRN)
+ catch exit:Reason ->
+ mnesia:abort(Reason)
end.
transform_table(Tab, Fun, NewA, NewRN) ->
@@ -2796,7 +2790,7 @@ pre_qlc(Opts, Tab) ->
end.
post_qlc(Tab) ->
- case catch get(mnesia_activity_state) of
+ case get(mnesia_activity_state) of
{_,#tid{},_} -> ok;
_ ->
case ?catch_val({Tab, setorbag}) of
diff --git a/lib/mnesia/src/mnesia.hrl b/lib/mnesia/src/mnesia.hrl
index c8010d5466..86b6fd908f 100644
--- a/lib/mnesia/src/mnesia.hrl
+++ b/lib/mnesia/src/mnesia.hrl
@@ -39,7 +39,12 @@
-define(ets_delete_table(Tab), ets:delete(Tab)).
-define(ets_fixtable(Tab, Bool), ets:fixtable(Tab, Bool)).
--define(catch_val(Var), (catch ?ets_lookup_element(mnesia_gvar, Var, 2))).
+
+-define(SAFE(OP), try (OP) catch error:_ -> ok end).
+-define(CATCH(OP), try (OP) catch _:_Reason -> {'EXIT', _Reason} end).
+
+-define(catch_val(Var), (try ?ets_lookup_element(mnesia_gvar, Var, 2)
+ catch error:_ -> {'EXIT', {badarg, []}} end)).
%% It's important that counter is first, since we compare tid's
@@ -53,7 +58,9 @@
up_stores = [], %% list of upper layer stores for nested trans
level = 1}). %% transaction level
--define(unique_cookie, {erlang:now(), node()}).
+-define(unique_cookie, {{erlang:monotonic_time() + erlang:time_offset(),
+ erlang:unique_integer(),1},
+ node()}).
-record(cstruct, {name, % Atom
type = set, % set | bag
diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl
index 3b084e7371..3fee952d77 100644
--- a/lib/mnesia/src/mnesia_bup.erl
+++ b/lib/mnesia/src/mnesia_bup.erl
@@ -78,24 +78,21 @@
%% BunchOfRecords will be [] when the iteration is done.
iterate(Mod, Fun, Opaque, Acc) ->
R = #restore{bup_module = Mod, bup_data = Opaque},
- case catch read_schema_section(R) of
- {error, Reason} ->
- {error, Reason};
- {R2, {Header, Schema, Rest}} ->
- case catch iter(R2, Header, Schema, Fun, Acc, Rest) of
- {ok, R3, Res} ->
- catch safe_apply(R3, close_read, [R3#restore.bup_data]),
- {ok, Res};
- {error, Reason} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- {error, Reason};
- {'EXIT', Pid, Reason} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- {error, {'EXIT', Pid, Reason}};
- {'EXIT', Reason} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- {error, {'EXIT', Reason}}
- end
+ try read_schema_section(R) of
+ {R2, {Header, Schema, Rest}} ->
+ try iter(R2, Header, Schema, Fun, Acc, Rest) of
+ {ok, R3, Res} ->
+ close_read(R3),
+ {ok, Res}
+ catch throw:Err ->
+ close_read(R2),
+ Err;
+ _:Reason ->
+ close_read(R2),
+ {error, {Reason, erlang:get_stacktrace()}}
+ end
+ catch throw:{error,_} = Err ->
+ Err
end.
iter(R, Header, Schema, Fun, Acc, []) ->
@@ -116,7 +113,7 @@ safe_apply(R, write, [_, Items]) when Items =:= [] ->
safe_apply(R, What, Args) ->
Abort = fun(Re) -> abort_restore(R, What, Args, Re) end,
Mod = R#restore.bup_module,
- case catch apply(Mod, What, Args) of
+ try apply(Mod, What, Args) of
{ok, Opaque, Items} when What =:= read ->
{R#restore{bup_data = Opaque}, Items};
{ok, Opaque} when What =/= read->
@@ -125,16 +122,19 @@ safe_apply(R, What, Args) ->
Abort(Re);
Re ->
Abort(Re)
+ catch _:Re ->
+ Abort(Re)
end.
-abort_restore(R, What, Args, Reason) ->
- Mod = R#restore.bup_module,
- Opaque = R#restore.bup_data,
+abort_restore(R = #restore{bup_module=Mod}, What, Args, Reason) ->
dbg_out("Restore aborted. ~p:~p~p -> ~p~n",
[Mod, What, Args, Reason]),
- catch apply(Mod, close_read, [Opaque]),
+ close_read(R),
throw({error, Reason}).
+close_read(#restore{bup_module=Mod, bup_data=Opaque}) ->
+ ?SAFE(Mod:close_read(Opaque)).
+
fallback_to_schema() ->
Fname = fallback_bup(),
fallback_to_schema(Fname).
@@ -145,40 +145,30 @@ fallback_to_schema(Fname) ->
{error, Reason} ->
{error, Reason};
Schema ->
- case catch lookup_schema(schema, Schema) of
- {error, _} ->
- {error, "No schema in fallback"};
- List ->
- {ok, fallback, List}
+ try lookup_schema(schema, Schema) of
+ List -> {ok, fallback, List}
+ catch throw:_ ->
+ {error, "No schema in fallback"}
end
end.
%% Opens Opaque reads schema and then close
read_schema(Mod, Opaque) ->
R = #restore{bup_module = Mod, bup_data = Opaque},
- case catch read_schema_section(R) of
- {error, Reason} ->
- {error, Reason};
- {R2, {_Header, Schema, _}} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- Schema
+ try read_schema_section(R) of
+ {_, {_Header, Schema, _}} -> Schema
+ catch throw:{error,_} = Error ->
+ Error
+ after close_read(R)
end.
%% Open backup media and extract schema
%% rewind backup media and leave it open
%% Returns {R, {Header, Schema}}
read_schema_section(R) ->
- case catch do_read_schema_section(R) of
- {'EXIT', Reason} ->
- catch safe_apply(R, close_read, [R#restore.bup_data]),
- {error, {'EXIT', Reason}};
- {error, Reason} ->
- catch safe_apply(R, close_read, [R#restore.bup_data]),
- {error, Reason};
- {R2, {H, Schema, Rest}} ->
- Schema2 = convert_schema(H#log_header.log_version, Schema),
- {R2, {H, Schema2, Rest}}
- end.
+ {R2, {H, Schema, Rest}} = do_read_schema_section(R),
+ Schema2 = convert_schema(H#log_header.log_version, Schema),
+ {R2, {H, Schema2, Rest}}.
do_read_schema_section(R) ->
R2 = safe_apply(R, open_read, [R#restore.bup_data]),
@@ -201,7 +191,7 @@ do_read_schema_section(R, {ok, B, _C, Rest}, Acc) ->
{R, {B, Acc, Rest}};
do_read_schema_section(_R, {error, Reason}, _Acc) ->
- {error, Reason}.
+ throw({error, Reason}).
verify_header([H | RawSchema]) when is_record(H, log_header) ->
Current = mnesia_log:backup_log_header(),
@@ -218,7 +208,7 @@ verify_header([H | RawSchema]) when is_record(H, log_header) ->
{error, {"Bad kind of header. Cannot be used as backup.", H}}
end;
verify_header(RawSchema) ->
- {error, {"Missing header. Cannot be used as backup.", catch hd(RawSchema)}}.
+ {error, {"Missing header. Cannot be used as backup.", ?CATCH(hd(RawSchema))}}.
refresh_cookie(Schema, NewCookie) ->
case lists:keysearch(schema, 2, Schema) of
@@ -345,7 +335,7 @@ create_schema(Ns, ok) ->
Str = mk_str(),
File = mnesia_lib:dir(Str),
file:delete(File),
- case catch make_initial_backup(Ns, File, Mod) of
+ try make_initial_backup(Ns, File, Mod) of
{ok, _Res} ->
case do_install_fallback(File, Mod) of
ok ->
@@ -353,8 +343,8 @@ create_schema(Ns, ok) ->
ok;
{error, Reason} ->
{error, Reason}
- end;
- {error, Reason} ->
+ end
+ catch throw:{error, Reason} ->
{error, Reason}
end
end
@@ -368,7 +358,7 @@ create_schema(_Ns, Reason) ->
{error, Reason}.
mk_str() ->
- Now = [integer_to_list(I) || I <- tuple_to_list(now())],
+ Now = integer_to_list(erlang:unique_integer([positive])),
lists:concat([node()] ++ Now ++ ".TMP").
make_initial_backup(Ns, Opaque, Mod) ->
@@ -384,10 +374,11 @@ make_initial_backup(Ns, Opaque, Mod) ->
do_apply(_, write, [_, Items], Opaque) when Items =:= [] ->
Opaque;
do_apply(Mod, What, Args, _Opaque) ->
- case catch apply(Mod, What, Args) of
+ try apply(Mod, What, Args) of
{ok, Opaque2} -> Opaque2;
- {error, Reason} -> throw({error, Reason});
- {'EXIT', Reason} -> throw({error, {'EXIT', Reason}})
+ {error, Reason} -> throw({error, Reason})
+ catch _:Reason ->
+ throw({error, {'EXIT', Reason}})
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -425,11 +416,11 @@ do_install_fallback(_Opaque, Args) ->
{error, {badarg, Args}}.
check_fallback_args([Arg | Tail], FA) ->
- case catch check_fallback_arg_type(Arg, FA) of
- {'EXIT', _Reason} ->
- {error, {badarg, Arg}};
+ try check_fallback_arg_type(Arg, FA) of
FA2 ->
check_fallback_args(Tail, FA2)
+ catch error:_ ->
+ {error, {badarg, Arg}}
end;
check_fallback_args([], FA) ->
{ok, FA}.
@@ -484,7 +475,7 @@ install_fallback_master(ClientPid, FA) ->
State = {start, FA},
Opaque = FA#fallback_args.opaque,
Mod = FA#fallback_args.module,
- Res = (catch iterate(Mod, fun restore_recs/4, Opaque, State)),
+ Res = iterate(Mod, fun restore_recs/4, Opaque, State),
unlink(ClientPid),
ClientPid ! {self(), Res},
exit(shutdown).
@@ -496,9 +487,7 @@ restore_recs(Recs, Header, Schema, {start, FA}) ->
%% No records in backup
Schema2 = convert_schema(Header#log_header.log_version, Schema),
CreateList = lookup_schema(schema, Schema2),
- case catch mnesia_schema:list2cs(CreateList) of
- {'EXIT', Reason} ->
- throw({error, {"Bad schema in restore_recs", Reason}});
+ try mnesia_schema:list2cs(CreateList) of
Cs ->
Ns = get_fallback_nodes(FA, Cs#cstruct.disc_copies),
global:set_lock({{mnesia_table_lock, schema}, self()}, Ns, infinity),
@@ -508,6 +497,8 @@ restore_recs(Recs, Header, Schema, {start, FA}) ->
Res = restore_recs(Recs, Header, Schema2, Pids),
global:del_lock({{mnesia_table_lock, schema}, self()}, Ns),
Res
+ catch _:Reason ->
+ throw({error, {"Bad schema in restore_recs", Reason}})
end;
restore_recs([], _Header, _Schema, Pids) ->
@@ -579,45 +570,46 @@ fallback_tmp_name() -> "FALLBACK.TMP".
fallback_receiver(Master, FA) ->
process_flag(trap_exit, true),
- case catch register(mnesia_fallback, self()) of
- {'EXIT', _} ->
- Reason = {already_exists, node()},
- local_fallback_error(Master, Reason);
- true ->
- FA2 = check_fallback_dir(Master, FA),
- Bup = FA2#fallback_args.fallback_bup,
- case mnesia_lib:exists(Bup) of
- true ->
- Reason2 = {already_exists, node()},
- local_fallback_error(Master, Reason2);
- false ->
- Mod = mnesia_backup,
- Tmp = FA2#fallback_args.fallback_tmp,
- R = #restore{mode = replace,
- bup_module = Mod,
- bup_data = Tmp},
- file:delete(Tmp),
- case catch fallback_receiver_loop(Master, R, FA2, schema) of
- {error, Reason} ->
- local_fallback_error(Master, Reason);
- Other ->
- exit(Other)
- end
- end
- end.
+ Res = try
+ register(mnesia_fallback, self()),
+ FA2 = check_fallback_dir(FA),
+ Bup = FA2#fallback_args.fallback_bup,
+ false = mnesia_lib:exists(Bup),
+ Mod = mnesia_backup,
+ Tmp = FA2#fallback_args.fallback_tmp,
+ R = #restore{mode = replace,
+ bup_module = Mod,
+ bup_data = Tmp},
+ file:delete(Tmp),
+ fallback_receiver_loop(Master, R, FA2, schema)
+ catch
+ error:_ ->
+ Reason = {already_exists, node()},
+ local_fallback_error(Master, Reason);
+ throw:{error, Reason} ->
+ local_fallback_error(Master, Reason)
+ end,
+ exit(Res).
local_fallback_error(Master, Reason) ->
Master ! {self(), {error, Reason}},
unlink(Master),
exit(Reason).
+
check_fallback_dir(Master, FA) ->
+ try check_fallback_dir(FA)
+ catch throw:{error,Reason} ->
+ local_fallback_error(Master, Reason)
+ end.
+
+check_fallback_dir(FA) ->
case mnesia:system_info(schema_location) of
ram ->
Reason = {has_no_disc, node()},
- local_fallback_error(Master, Reason);
+ throw({error, Reason});
_ ->
- Dir = check_fallback_dir_arg(Master, FA),
+ Dir = check_fallback_dir_arg(FA),
Bup = filename:join([Dir, fallback_name()]),
Tmp = filename:join([Dir, fallback_tmp_name()]),
FA#fallback_args{fallback_bup = Bup,
@@ -625,22 +617,20 @@ check_fallback_dir(Master, FA) ->
mnesia_dir = Dir}
end.
-check_fallback_dir_arg(Master, FA) ->
+check_fallback_dir_arg(FA) ->
case FA#fallback_args.use_default_dir of
true ->
mnesia_lib:dir();
false when FA#fallback_args.scope =:= local ->
Dir = FA#fallback_args.mnesia_dir,
- case catch mnesia_monitor:do_check_type(dir, Dir) of
- {'EXIT', _R} ->
+ try mnesia_monitor:do_check_type(dir, Dir)
+ catch _:_ ->
Reason = {badarg, {dir, Dir}, node()},
- local_fallback_error(Master, Reason);
- AbsDir->
- AbsDir
- end;
+ throw({error, Reason})
+ end;
false when FA#fallback_args.scope =:= global ->
Reason = {combine_error, global, dir, node()},
- local_fallback_error(Master, Reason)
+ throw({error, Reason})
end.
fallback_receiver_loop(Master, R, FA, State) ->
@@ -666,7 +656,7 @@ fallback_receiver_loop(Master, R, FA, State) ->
Bup = FA#fallback_args.fallback_bup,
Tmp = FA#fallback_args.fallback_tmp,
throw_bad_res(ok, file:rename(Tmp, Bup)),
- catch mnesia_lib:set(active_fallback, true),
+ ?SAFE(mnesia_lib:set(active_fallback, true)),
?eval_debug_fun({?MODULE, fallback_receiver_loop, post_swap}, []),
Master ! {self(), ok},
fallback_receiver_loop(Master, R, FA, stop);
@@ -697,7 +687,7 @@ throw_bad_res(_Expected, Actual) -> throw({error, Actual}).
tm_fallback_start(IgnoreFallback) ->
mnesia_schema:lock_schema(),
Res = do_fallback_start(fallback_exists(), IgnoreFallback),
- mnesia_schema: unlock_schema(),
+ mnesia_schema:unlock_schema(),
case Res of
ok -> ok;
{error, Reason} -> exit(Reason)
@@ -715,9 +705,9 @@ do_fallback_start(true, false) ->
BupFile = fallback_bup(),
Mod = mnesia_backup,
LocalTabs = ?ets_new_table(mnesia_local_tables, [set, public, {keypos, 2}]),
- case catch iterate(Mod, fun restore_tables/4, BupFile, {start, LocalTabs}) of
+ case iterate(Mod, fun restore_tables/4, BupFile, {start, LocalTabs}) of
{ok, _Res} ->
- catch dets:close(schema),
+ ?SAFE(dets:close(schema)),
TmpSchema = mnesia_lib:tab2tmp(schema),
DatSchema = mnesia_lib:tab2dat(schema),
AllLT = ?ets_match_object(LocalTabs, '_'),
@@ -733,8 +723,6 @@ do_fallback_start(true, false) ->
{error, {"Cannot start from fallback. Rename error.", Reason}}
end;
{error, Reason} ->
- {error, {"Cannot start from fallback", Reason}};
- {'EXIT', Reason} ->
{error, {"Cannot start from fallback", Reason}}
end.
@@ -996,10 +984,10 @@ uninstall_fallback_master(ClientPid, FA) ->
case fallback_to_schema(Bup) of
{ok, fallback, List} ->
Cs = mnesia_schema:list2cs(List),
- case catch get_fallback_nodes(FA, Cs#cstruct.disc_copies) of
+ try get_fallback_nodes(FA, Cs#cstruct.disc_copies) of
Ns when is_list(Ns) ->
- do_uninstall(ClientPid, Ns, FA);
- {error, Reason} ->
+ do_uninstall(ClientPid, Ns, FA)
+ catch throw:{error, Reason} ->
local_fallback_error(ClientPid, Reason)
end;
{error, Reason} ->
@@ -1042,13 +1030,13 @@ local_uninstall_fallback(Master, FA) ->
%% Don't trap exit
register(mnesia_fallback, self()), % May exit
- FA2 = check_fallback_dir(Master, FA), % May exit
+ FA2 = check_fallback_dir(Master, FA), % May exit
Master ! {self(), started},
receive
{Master, do_uninstall} ->
?eval_debug_fun({?MODULE, uninstall_fallback2, pre_delete}, []),
- catch mnesia_lib:set(active_fallback, false),
+ ?SAFE(mnesia_lib:set(active_fallback, false)),
Tmp = FA2#fallback_args.fallback_tmp,
Bup = FA2#fallback_args.fallback_bup,
file:delete(Tmp),
@@ -1071,10 +1059,8 @@ rec_uninstall(ClientPid, [Pid | Pids], AccRes) ->
{Pid, BadRes} ->
rec_uninstall(ClientPid, Pids, BadRes)
end;
-rec_uninstall(ClientPid, [], Res) ->
- ClientPid ! {self(), Res},
- unlink(ClientPid),
- exit(normal).
+rec_uninstall(_, [], Res) ->
+ Res.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Backup traversal
@@ -1125,12 +1111,11 @@ do_traverse_backup(ClientPid, Source, SourceMod, Target, TargetMod, Fun, Acc) ->
Iter =
if
TargetMod =/= read_only ->
- case catch do_apply(TargetMod, open_write, [Target], Target) of
- {error, Error} ->
+ try do_apply(TargetMod, open_write, [Target], Target)
+ catch throw:{error, Error} ->
unlink(ClientPid),
ClientPid ! {iter_done, self(), {error, Error}},
- exit(Error);
- Else -> Else
+ exit(Error)
end;
true ->
ignore
@@ -1139,16 +1124,16 @@ do_traverse_backup(ClientPid, Source, SourceMod, Target, TargetMod, Fun, Acc) ->
Res =
case iterate(SourceMod, fun trav_apply/4, Source, A) of
{ok, {iter, _, Acc2, _, Iter2}} when TargetMod =/= read_only ->
- case catch do_apply(TargetMod, commit_write, [Iter2], Iter2) of
- {error, Reason} ->
- {error, Reason};
- _ ->
- {ok, Acc2}
+ try
+ do_apply(TargetMod, commit_write, [Iter2], Iter2),
+ {ok, Acc2}
+ catch throw:{error, Reason} ->
+ {error, Reason}
end;
{ok, {iter, _, Acc2, _, _}} ->
{ok, Acc2};
{error, Reason} when TargetMod =/= read_only->
- catch do_apply(TargetMod, abort_write, [Iter], Iter),
+ ?CATCH(do_apply(TargetMod, abort_write, [Iter], Iter)),
{error, {"Backup traversal failed", Reason}};
{error, Reason} ->
{error, {"Backup traversal failed", Reason}}
diff --git a/lib/mnesia/src/mnesia_checkpoint.erl b/lib/mnesia/src/mnesia_checkpoint.erl
index 173e3be2f5..0a3ea8d769 100644
--- a/lib/mnesia/src/mnesia_checkpoint.erl
+++ b/lib/mnesia/src/mnesia_checkpoint.erl
@@ -68,12 +68,12 @@
-import(mnesia_lib, [add/2, del/2, set/2, unset/1]).
-import(mnesia_lib, [dbg_out/2]).
--record(checkpoint_args, {name = {now(), node()},
+-record(checkpoint_args, {name = {erlang:unique_integer([positive]), node()},
allow_remote = true,
ram_overrides_dump = false,
nodes = [],
node = node(),
- now = now(),
+ now, %% unused
cookie = ?unique_cookie,
min = [],
max = [],
@@ -128,7 +128,7 @@ tm_enter_pending([], Pending) ->
Pending;
tm_enter_pending([Tab | Tabs], Pending) ->
%% io:format("Add ~p ~p ~p~n",[Tab, Pending, hd(tl(element(2, process_info(self(), current_stacktrace))))]),
- catch ?ets_insert(Tab, Pending),
+ ?SAFE(?ets_insert(Tab, Pending)),
tm_enter_pending(Tabs, Pending).
tm_exit_pending(Tid) ->
@@ -427,22 +427,22 @@ check_tables(Cp) ->
arrange_retainers(Cp, Overriders, AllTabs) ->
R = #retainer{cp_name = Cp#checkpoint_args.name},
- case catch [R#retainer{tab_name = Tab,
- writers = select_writers(Cp, Tab)}
- || Tab <- AllTabs] of
- {'EXIT', Reason} ->
- {error, Reason};
+ try [R#retainer{tab_name = Tab,
+ writers = select_writers(Cp, Tab)}
+ || Tab <- AllTabs] of
Retainers ->
{ok, Cp#checkpoint_args{ram_overrides_dump = Overriders,
- retainers = Retainers,
- nodes = writers(Retainers)}}
+ retainers = Retainers,
+ nodes = writers(Retainers)}}
+ catch throw:Reason ->
+ {error, Reason}
end.
select_writers(Cp, Tab) ->
case filter_remote(Cp, val({Tab, active_replicas})) of
[] ->
- exit({"Cannot prepare checkpoint (replica not available)",
- [Tab, Cp#checkpoint_args.name]});
+ throw({"Cannot prepare checkpoint (replica not available)",
+ [Tab, Cp#checkpoint_args.name]});
Writers ->
This = node(),
case {lists:member(Tab, Cp#checkpoint_args.max),
@@ -492,12 +492,12 @@ check_prep([], Name, Nodes, IgnoreNew) ->
collect_pending(Name, Nodes, IgnoreNew) ->
case rpc:multicall(Nodes, ?MODULE, call, [Name, collect_pending]) of
{Replies, []} ->
- case catch ?ets_new_table(mnesia_union, [bag]) of
- {'EXIT', Reason} -> %% system limit
+ try
+ UnionTab = ?ets_new_table(mnesia_union, [bag]),
+ compute_union(Replies, Nodes, Name, UnionTab, IgnoreNew)
+ catch error:Reason -> %% system limit
Msg = "Cannot create an ets table pending union",
- {error, {system_limit, Msg, Reason}};
- UnionTab ->
- compute_union(Replies, Nodes, Name, UnionTab, IgnoreNew)
+ {error, {system_limit, Msg, Reason}}
end;
{_, BadNodes} ->
deactivate(Nodes, Name),
@@ -1170,7 +1170,7 @@ iterate(Name, Tab, Fun, Acc, Source, Val) ->
{error, Reason};
{ok, Iter, Pid} ->
link(Pid), % We don't want any pending fixtable's
- Res = (catch iter(Fun, Acc, Iter)),
+ Res = ?CATCH(iter(Fun, Acc, Iter)),
unlink(Pid),
call(Name, {iter_end, Iter}),
case Res of
@@ -1246,7 +1246,7 @@ system_code_change(Cp, _Module, _OldVsn, _Extra) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
+ _VaLuE_ -> _VaLuE_
end.
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 5a9bae54da..b9d3779e9a 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -51,6 +51,7 @@
force_load_table/1,
async_dump_log/1,
sync_dump_log/1,
+ snapshot_dcd/1,
connect_nodes/1,
connect_nodes/2,
wait_for_schema_commit_lock/0,
@@ -139,7 +140,8 @@ max_loaders() ->
-record(block_controller, {owner}).
-record(dump_log, {initiated_by,
- opt_reply_to
+ opt_reply_to,
+ operation = dump_log
}).
-record(net_load, {table,
@@ -184,7 +186,7 @@ max_loaders() ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
Value -> Value
end.
@@ -201,6 +203,15 @@ async_dump_log(InitBy) ->
?SERVER_NAME ! {async_dump_log, InitBy},
ok.
+snapshot_dcd(Tables) when is_list(Tables) ->
+ case [T || T <- Tables,
+ mnesia_lib:storage_type_at_node(node(), T) =/= disc_copies] of
+ [] ->
+ call({snapshot_dcd, Tables});
+ BadTabs ->
+ {error, {not_disc_copies, BadTabs}}
+ end.
+
%% Wait for tables to be active
%% If needed, we will wait for Mnesia to start
%% If Mnesia stops, we will wait for Mnesia to restart
@@ -230,9 +241,7 @@ do_wait_for_tables(Tabs, Timeout) ->
end.
reply_wait(Tabs) ->
- case catch mnesia_lib:active_tables() of
- {'EXIT', _} ->
- {error, {node_not_running, node()}};
+ try mnesia_lib:active_tables() of
Active when is_list(Active) ->
case Tabs -- Active of
[] ->
@@ -240,6 +249,7 @@ reply_wait(Tabs) ->
BadTabs ->
{timeout, BadTabs}
end
+ catch exit:_ -> {error, {node_not_running, node()}}
end.
wait_for_tables_init(From, Tabs) ->
@@ -250,13 +260,12 @@ wait_for_tables_init(From, Tabs) ->
exit(normal).
wait_for_init(From, Tabs, Init) ->
- case catch link(Init) of
- {'EXIT', _} ->
- %% Mnesia is not started
- {error, {node_not_running, node()}};
+ try link(Init) of
true when is_pid(Init) ->
cast({sync_tabs, Tabs, self()}),
rec_tabs(Tabs, Tabs, From, Init)
+ catch error:_ -> %% Mnesia is not started
+ {error, {node_not_running, node()}}
end.
sync_reply(Waiter, Tab) ->
@@ -332,7 +341,7 @@ get_network_copy(Tab, Cs) ->
%% might be solved by using monitor in subscr instead.
process_flag(trap_exit, true),
Load = load_table_fun(Work),
- Res = (catch Load()),
+ Res = ?CATCH(Load()),
process_flag(trap_exit, false),
call({del_other, self()}),
case Res of
@@ -581,11 +590,8 @@ call(Msg) ->
end.
remote_call(Node, Func, Args) ->
- case catch gen_server:call({?MODULE, Node}, {Func, Args, self()}, infinity) of
- {'EXIT', Error} ->
- {error, Error};
- Else ->
- Else
+ try gen_server:call({?MODULE, Node}, {Func, Args, self()}, infinity)
+ catch exit:Error -> {error, Error}
end.
multicall(Nodes, Msg) ->
@@ -646,6 +652,15 @@ handle_call({sync_dump_log, InitBy}, From, State) ->
State2 = add_worker(Worker, State),
noreply(State2);
+handle_call({snapshot_dcd, Tables}, From, State) ->
+ Worker = #dump_log{initiated_by = user,
+ opt_reply_to = From,
+ operation = fun() ->
+ mnesia_dumper:snapshot_dcd(Tables)
+ end},
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
handle_call(wait_for_schema_commit_lock, From, State) ->
Worker = #schema_commit_lock{owner = From},
State2 = add_worker(Worker, State),
@@ -657,7 +672,7 @@ handle_call(block_controller, From, State) ->
noreply(State2);
handle_call({update,Fun}, From, State) ->
- Res = (catch Fun()),
+ Res = ?CATCH(Fun()),
reply(From, Res),
noreply(State);
@@ -1236,7 +1251,7 @@ handle_info(#sender_done{worker_pid=Pid, worker_res=Res}, State) ->
end;
handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
- catch set(mnesia_status, stopping),
+ ?SAFE(set(mnesia_status, stopping)),
case State#state.dumper_pid of
undefined ->
dbg_out("~p was ~p~n", [?SERVER_NAME, R]),
@@ -1460,9 +1475,9 @@ orphan_tables([], _, _, LocalOrphans, RemoteMasters) ->
node_has_tabs([Tab | Tabs], Node, State) when Node /= node() ->
State2 =
- case catch update_whereabouts(Tab, Node, State) of
- State1 = #state{} -> State1;
- {'EXIT', R} -> %% Tab was just deleted?
+ try update_whereabouts(Tab, Node, State) of
+ State1 = #state{} -> State1
+ catch exit:R -> %% Tab was just deleted?
case ?catch_val({Tab, cstruct}) of
{'EXIT', _} -> State; % yes
_ -> erlang:error(R)
@@ -1748,22 +1763,17 @@ change_table_majority(Cs) ->
update_where_to_wlock(Tab) ->
WNodes = val({Tab, where_to_write}),
- Majority = case catch val({Tab, majority}) of
- true -> true;
- _ -> false
- end,
+ Majority = ?catch_val({Tab, majority}) == true,
set({Tab, where_to_wlock}, {WNodes, Majority}).
%% node To now has tab loaded, but this must be undone
%% This code is rpc:call'ed from the tab_copier process
%% when it has *not* released it's table lock
unannounce_add_table_copy(Tab, To) ->
- catch del_active_replica(Tab, To),
- case catch val({Tab , where_to_read}) of
- To ->
- mnesia_lib:set_remote_where_to_read(Tab);
- _ ->
- ignore
+ ?SAFE(del_active_replica(Tab, To)),
+ try To = val({Tab , where_to_read}),
+ mnesia_lib:set_remote_where_to_read(Tab)
+ catch _:_ -> ignore
end.
user_sync_tab(Tab) ->
@@ -2089,7 +2099,12 @@ start_remote_sender(Node, Tab, Receiver, Storage) ->
dump_and_reply(ReplyTo, Worker) ->
%% No trap_exit, die intentionally instead
- Res = mnesia_dumper:opt_dump_log(Worker#dump_log.initiated_by),
+ Res = case Worker#dump_log.operation of
+ dump_log ->
+ mnesia_dumper:opt_dump_log(Worker#dump_log.initiated_by);
+ F when is_function(F, 0) ->
+ F()
+ end,
ReplyTo ! #dumper_done{worker_pid = self(),
worker_res = Res},
unlink(ReplyTo),
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index 14665797a0..693f20dbc2 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -34,11 +34,13 @@
-export([
get_log_writes/0,
incr_log_writes/0,
+ needs_dump_ets/1,
raw_dump_table/2,
raw_named_dump_table/2,
start_regulator/0,
opt_dump_log/1,
- update/3
+ update/3,
+ snapshot_dcd/1
]).
%% Internal stuff
@@ -99,6 +101,19 @@ opt_dump_log(InitBy) ->
end,
perform_dump(InitBy, Reg).
+snapshot_dcd(Tables) ->
+ lists:foreach(
+ fun(Tab) ->
+ case mnesia_lib:storage_type_at_node(node(), Tab) of
+ disc_copies ->
+ mnesia_log:ets2dcd(Tab);
+ _ ->
+ %% Storage type was checked before queueing the op, though
+ skip
+ end
+ end, Tables),
+ dumped.
+
%% Scan for decisions
perform_dump(InitBy, Regulator) when InitBy == scan_decisions ->
?eval_debug_fun({?MODULE, perform_dump}, [InitBy]),
@@ -122,7 +137,7 @@ perform_dump(InitBy, Regulator) ->
U = mnesia_monitor:get_env(dump_log_update_in_place),
Cont = mnesia_log:init_log_dump(),
mnesia_recover:sync(),
- case catch do_perform_dump(Cont, U, InitBy, Regulator, undefined) of
+ try do_perform_dump(Cont, U, InitBy, Regulator, undefined) of
ok ->
?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
case mnesia_monitor:use_dir() of
@@ -133,17 +148,15 @@ perform_dump(InitBy, Regulator) ->
end,
mnesia_recover:allow_garb(),
%% And now to the crucial point...
- mnesia_log:confirm_log_dump(Diff);
- {error, Reason} ->
- {error, Reason};
- {'EXIT', {Desc, Reason}} ->
+ mnesia_log:confirm_log_dump(Diff)
+ catch exit:Reason when Reason =/= fatal ->
case mnesia_monitor:get_env(auto_repair) of
true ->
- mnesia_lib:important(Desc, Reason),
+ mnesia_lib:important(error, Reason),
%% Ignore rest of the log
mnesia_log:confirm_log_dump(Diff);
false ->
- fatal(Desc, Reason)
+ fatal(error, Reason)
end
end;
{error, Reason} ->
@@ -161,24 +174,25 @@ scan_decisions(Fname, InitBy, Regulator) ->
mnesia_log:open_log(Name, Header, Fname, Exists,
mnesia_monitor:get_env(auto_repair), read_only),
Cont = start,
- Res = (catch do_perform_dump(Cont, false, InitBy, Regulator, undefined)),
- mnesia_log:close_log(Name),
- case Res of
- ok -> ok;
- {'EXIT', Reason} -> {error, Reason}
+ try
+ do_perform_dump(Cont, false, InitBy, Regulator, undefined)
+ catch exit:Reason when Reason =/= fatal ->
+ {error, Reason}
+ after mnesia_log:close_log(Name)
end
end.
do_perform_dump(Cont, InPlace, InitBy, Regulator, OldVersion) ->
case mnesia_log:chunk_log(Cont) of
{C2, Recs} ->
- case catch insert_recs(Recs, InPlace, InitBy, Regulator, OldVersion) of
- {'EXIT', R} ->
- Reason = {"Transaction log dump error: ~p~n", [R]},
- close_files(InPlace, {error, Reason}, InitBy),
- exit(Reason);
+ try insert_recs(Recs, InPlace, InitBy, Regulator, OldVersion) of
Version ->
do_perform_dump(C2, InPlace, InitBy, Regulator, Version)
+ catch _:R when R =/= fatal ->
+ ST = erlang:get_stacktrace(),
+ Reason = {"Transaction log dump error: ~p~n", [{R, ST}]},
+ close_files(InPlace, {error, Reason}, InitBy),
+ exit(Reason)
end;
eof ->
close_files(InPlace, ok, InitBy),
@@ -288,17 +302,16 @@ perform_update(Tid, SchemaOps, _DumperMode, _UseDir) ->
InitBy = fast_schema_update,
InPlace = mnesia_monitor:get_env(dump_log_update_in_place),
- ?eval_debug_fun({?MODULE, dump_schema_op}, [InitBy]),
- case catch insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy,
- mnesia_log:version()) of
- {'EXIT', Reason} ->
- Error = {error, {"Schema update error", Reason}},
+ try insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy,
+ mnesia_log:version()),
+ ?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
+ close_files(InPlace, ok, InitBy),
+ ok
+ catch _:Reason when Reason =/= fatal ->
+ ST = erlang:get_stacktrace(),
+ Error = {error, {"Schema update error", {Reason, ST}}},
close_files(InPlace, Error, InitBy),
- fatal("Schema update error ~p ~p", [Reason, SchemaOps]);
- _ ->
- ?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
- close_files(InPlace, ok, InitBy),
- ok
+ fatal("Schema update error ~p ~p", [{Reason,ST}, SchemaOps])
end.
insert_ops(_Tid, _Storage, [], _InPlace, _InitBy, _) -> ok;
@@ -347,13 +360,11 @@ dets_insert(Op,Tab,Key,Val) ->
case dets_incr_counter(Tab,Key) of
true ->
{RecName, Incr} = Val,
- case catch dets:update_counter(Tab, Key, Incr) of
- CounterVal when is_integer(CounterVal) ->
- ok;
- _ when Incr < 0 ->
+ try _ = dets:update_counter(Tab, Key, Incr)
+ catch error:_ when Incr < 0 ->
Zero = {RecName, Key, 0},
ok = dets:insert(Tab, Zero);
- _ ->
+ error:_ ->
Init = {RecName, Key, Incr},
ok = dets:insert(Tab, Init)
end;
@@ -771,7 +782,7 @@ insert_op(Tid, _, {op, clear_table, TabDef}, InPlace, InitBy) ->
end,
%% Need to catch this, it crashes on ram_copies if
%% the op comes before table is loaded at startup.
- catch insert(Tid, Storage, Tab, '_', Oid, clear_table, InPlace, InitBy)
+ ?CATCH(insert(Tid, Storage, Tab, '_', Oid, clear_table, InPlace, InitBy))
end;
insert_op(Tid, _, {op, merge_schema, TabDef}, InPlace, InitBy) ->
@@ -981,28 +992,10 @@ open_files(_Tab, _Storage, _UpdateInPlace, _InitBy) ->
false.
open_disc_copies(Tab, InitBy) ->
- DclF = mnesia_lib:tab2dcl(Tab),
- DumpEts =
- case file:read_file_info(DclF) of
- {error, enoent} ->
- false;
- {ok, DclInfo} ->
- DcdF = mnesia_lib:tab2dcd(Tab),
- case file:read_file_info(DcdF) of
- {error, Reason} ->
- mnesia_lib:dbg_out("File ~p info_error ~p ~n",
- [DcdF, Reason]),
- true;
- {ok, DcdInfo} ->
- Mul = case ?catch_val(dc_dump_limit) of
- {'EXIT', _} -> ?DumpToEtsMultiplier;
- Val -> Val
- end,
- DcdInfo#file_info.size =< (DclInfo#file_info.size * Mul)
- end
- end,
+ DumpEts = needs_dump_ets(Tab),
if
DumpEts == false; InitBy == startup ->
+ DclF = mnesia_lib:tab2dcl(Tab),
mnesia_log:open_log({?MODULE,Tab},
mnesia_log:dcl_log_header(),
DclF,
@@ -1017,6 +1010,27 @@ open_disc_copies(Tab, InitBy) ->
false
end.
+needs_dump_ets(Tab) ->
+ DclF = mnesia_lib:tab2dcl(Tab),
+ case file:read_file_info(DclF) of
+ {error, enoent} ->
+ false;
+ {ok, DclInfo} ->
+ DcdF = mnesia_lib:tab2dcd(Tab),
+ case file:read_file_info(DcdF) of
+ {error, Reason} ->
+ mnesia_lib:dbg_out("File ~p info_error ~p ~n",
+ [DcdF, Reason]),
+ true;
+ {ok, DcdInfo} ->
+ Mul = case ?catch_val(dc_dump_limit) of
+ {'EXIT', _} -> ?DumpToEtsMultiplier;
+ Val -> Val
+ end,
+ DcdInfo#file_info.size =< (DclInfo#file_info.size * Mul)
+ end
+ end.
+
%% Always opens the dcl file for writing overriding already_dumped
%% mechanismen, used for schema transactions.
open_dcl(Tab) ->
@@ -1042,14 +1056,13 @@ prepare_open(Tab, UpdateInPlace) ->
Dat;
false ->
Tmp = mnesia_lib:tab2tmp(Tab),
- case catch mnesia_lib:copy_file(Dat, Tmp) of
- ok ->
- Tmp;
- Error ->
+ try ok = mnesia_lib:copy_file(Dat, Tmp)
+ catch error:Error ->
fatal("Cannot copy dets file ~p to ~p: ~p~n",
[Dat, Tmp, Error])
- end
- end.
+ end,
+ Tmp
+ end.
del_opened_tab(Tab) ->
erase({?MODULE, Tab}).
@@ -1171,18 +1184,16 @@ raw_named_dump_table(Tab, Ftype) ->
Storage = ram_copies,
mnesia_lib:db_fixtable(Storage, Tab, true),
- case catch raw_dump_table(TabRef, Tab) of
- {'EXIT', Reason} ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_lib:dets_sync_close(Tab),
- file:delete(TmpFname),
- mnesia_lib:unlock_table(Tab),
- exit({"Dump of table to disc failed", Reason});
- ok ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_lib:dets_sync_close(Tab),
- mnesia_lib:unlock_table(Tab),
- ok = file:rename(TmpFname, Fname)
+ try
+ ok = raw_dump_table(TabRef, Tab),
+ ok = file:rename(TmpFname, Fname)
+ catch _:Reason ->
+ ?SAFE(file:delete(TmpFname)),
+ exit({"Dump of table to disc failed", Reason})
+ after
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ mnesia_lib:dets_sync_close(Tab),
+ mnesia_lib:unlock_table(Tab)
end;
{error, Reason} ->
mnesia_lib:unlock_table(Tab),
@@ -1248,6 +1259,6 @@ regulate(RegulatorPid) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
Value -> Value
end.
diff --git a/lib/mnesia/src/mnesia_event.erl b/lib/mnesia/src/mnesia_event.erl
index 67ec9d7399..8a4be88e9a 100644
--- a/lib/mnesia/src/mnesia_event.erl
+++ b/lib/mnesia/src/mnesia_event.erl
@@ -235,8 +235,7 @@ report_fatal(Format, Args, BinaryCore, CoreDumped) ->
end.
core_file(CoreDir,BinaryCore,Format,Args) ->
- %% Integers = tuple_to_list(date()) ++ tuple_to_list(time()),
- Integers = tuple_to_list(now()),
+ Integers = tuple_to_list(erlang:timestamp()),
Fun = fun(I) when I < 10 -> ["_0",I];
(I) -> ["_",I]
end,
diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl
index 66fc20913c..6036ac4e8f 100644
--- a/lib/mnesia/src/mnesia_frag.erl
+++ b/lib/mnesia/src/mnesia_frag.erl
@@ -406,10 +406,11 @@ verify_numbers(FH,MatchSpec) ->
VerifyFun = fun(F) when is_integer(F), F >= 1, F =< N -> false;
(_F) -> true
end,
- case catch lists:filter(VerifyFun, FragNumbers) of
- [] ->
- FragNumbers;
- BadFrags ->
+ try
+ Frags = lists:filter(VerifyFun, FragNumbers),
+ Frags == [] orelse error(Frags),
+ FragNumbers
+ catch error:BadFrags ->
mnesia:abort({"match_spec_to_frag_numbers: Fragment numbers out of range",
BadFrags, {range, 1, N}})
end.
@@ -437,7 +438,7 @@ remote_select(ReplyTo, Ref, NameNodes, MatchSpec) ->
do_remote_select(ReplyTo, Ref, [{Name, Node} | NameNodes], MatchSpec) ->
if
Node == node() ->
- Res = (catch {ok, mnesia:dirty_select(Name, MatchSpec)}),
+ Res = ?CATCH({ok, mnesia:dirty_select(Name, MatchSpec)}),
ReplyTo ! {remote_select, Ref, Node, Res},
do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec);
true ->
@@ -886,17 +887,19 @@ adjust_before_split(FH) ->
HashMod:add_frag(HashState)
end,
N = FH#frag_state.n_fragments + 1,
- FromFrags2 = (catch lists:sort(FromFrags)),
- UnionFrags = (catch lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags))),
VerifyFun = fun(F) when is_integer(F), F >= 1, F =< N -> false;
(_F) -> true
end,
- case catch lists:filter(VerifyFun, UnionFrags) of
- [] ->
- FH2 = FH#frag_state{n_fragments = N,
- hash_state = HashState2},
- {FH2, FromFrags2, UnionFrags};
- BadFrags ->
+ try
+ FromFrags2 = lists:sort(FromFrags),
+ UnionFrags = lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags)),
+
+ Frags = lists:filter(VerifyFun, UnionFrags),
+ Frags == [] orelse error(Frags),
+ FH2 = FH#frag_state{n_fragments = N,
+ hash_state = HashState2},
+ {FH2, FromFrags2, UnionFrags}
+ catch error:BadFrags ->
mnesia:abort({"add_frag: Fragment numbers out of range",
BadFrags, {range, 1, N}})
end.
@@ -981,22 +984,24 @@ adjust_before_merge(FH) ->
HashMod:del_frag(HashState)
end,
N = FH#frag_state.n_fragments,
- FromFrags2 = (catch lists:sort(FromFrags)),
- UnionFrags = (catch lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags))),
VerifyFun = fun(F) when is_integer(F), F >= 1, F =< N -> false;
(_F) -> true
end,
- case catch lists:filter(VerifyFun, UnionFrags) of
- [] ->
- case lists:member(N, FromFrags2) of
- true ->
- FH2 = FH#frag_state{n_fragments = N - 1,
- hash_state = HashState2},
- {FH2, FromFrags2, UnionFrags};
+ try
+ FromFrags2 = lists:sort(FromFrags),
+ UnionFrags = lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags)),
+
+ Frags = lists:filter(VerifyFun, UnionFrags),
+ [] == Frags orelse error(Frags),
+ case lists:member(N, FromFrags2) of
+ true ->
+ FH2 = FH#frag_state{n_fragments = N - 1,
+ hash_state = HashState2},
+ {FH2, FromFrags2, UnionFrags};
false ->
- mnesia:abort({"del_frag: Last fragment number not included", N})
- end;
- BadFrags ->
+ mnesia:abort({"del_frag: Last fragment number not included", N})
+ end
+ catch error:BadFrags ->
mnesia:abort({"del_frag: Fragment numbers out of range",
BadFrags, {range, 1, N}})
end.
@@ -1141,8 +1146,8 @@ remove_node(Node, Cs) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
+ Value -> Value
end.
set_frag_hash(Tab, Props) ->
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index 87cb58dae1..6a7c964fce 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -45,21 +45,11 @@
del_transient/3,
del_index_table/3]).
--import(mnesia_lib, [verbose/2]).
+-import(mnesia_lib, [val/1, verbose/2]).
-include("mnesia.hrl").
-record(index, {setorbag, pos_list}).
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} ->
- case mnesia_lib:other_val(Var) of
- error -> mnesia_lib:pr_other(Var, _ReASoN_);
- Val -> Val
- end;
- _VaLuE_ -> _VaLuE_
- end.
-
%% read an object list throuh its index table
%% we assume that table Tab has index on attribute number Pos
diff --git a/lib/mnesia/src/mnesia_late_loader.erl b/lib/mnesia/src/mnesia_late_loader.erl
index d09de3ca66..9a113c6306 100644
--- a/lib/mnesia/src/mnesia_late_loader.erl
+++ b/lib/mnesia/src/mnesia_late_loader.erl
@@ -36,17 +36,19 @@
-define(SERVER_NAME, ?MODULE).
+-include("mnesia.hrl").
+
-record(state, {supervisor}).
async_late_disc_load(_, [], _) -> ok;
async_late_disc_load(Node, Tabs, Reason) ->
Msg = {async_late_disc_load, Tabs, Reason},
- catch ({?SERVER_NAME, Node} ! {self(), Msg}).
+ ?SAFE({?SERVER_NAME, Node} ! {self(), Msg}).
maybe_async_late_disc_load(_, [], _) -> ok;
maybe_async_late_disc_load(Node, Tabs, Reason) ->
Msg = {maybe_async_late_disc_load, Tabs, Reason},
- catch ({?SERVER_NAME, Node} ! {self(), Msg}).
+ ?SAFE({?SERVER_NAME, Node} ! {self(), Msg}).
start() ->
mnesia_monitor:start_proc(?SERVER_NAME, ?MODULE, init, [self()]).
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index a32c69c59e..fc7362a31d 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -114,9 +114,7 @@
lock_table/1,
mkcore/1,
not_active_here/1,
- other_val/2,
other_val/1,
- pr_other/2,
overload_read/0,
overload_read/1,
overload_set/2,
@@ -380,8 +378,8 @@ search_key(_Key, []) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
+ {'EXIT', _} -> other_val(Var);
+ _VaLuE_ -> _VaLuE_
end.
set(Var, Val) ->
@@ -390,13 +388,13 @@ set(Var, Val) ->
unset(Var) ->
?ets_delete(mnesia_gvar, Var).
-other_val(Var, Other) ->
- case other_val(Var) of
- error -> pr_other(Var, Other);
+other_val(Var) ->
+ case other_val_1(Var) of
+ error -> pr_other(Var);
Val -> Val
end.
-other_val(Var) ->
+other_val_1(Var) ->
case Var of
{_, where_to_read} -> nowhere;
{_, where_to_write} -> [];
@@ -404,21 +402,16 @@ other_val(Var) ->
_ -> error
end.
-pr_other(Var, Other) ->
- Why =
+pr_other(Var) ->
+ Why =
case is_running() of
no -> {node_not_running, node()};
_ -> {no_exists, Var}
end,
- verbose("~p (~p) val(mnesia_gvar, ~w) -> ~p ~p ~n",
+ verbose("~p (~p) val(mnesia_gvar, ~w) -> ~p ~n",
[self(), process_info(self(), registered_name),
- Var, Other, Why]),
- case Other of
- {badarg, [{ets, lookup_element, _, _}|_]} ->
- exit(Why);
- _ ->
- erlang:error(Why)
- end.
+ Var, Why]),
+ mnesia:abort(Why).
%% Some functions for list valued variables
add(Var, Val) ->
@@ -905,7 +898,7 @@ dirty_rpc_error_tag(Reason) ->
end.
fatal(Format, Args) ->
- catch set(mnesia_status, stopping),
+ ?SAFE(catch set(mnesia_status, stopping)),
Core = mkcore({crashinfo, {Format, Args}}),
report_fatal(Format, Args, Core),
timer:sleep(10000), % Enough to write the core dump to disc?
@@ -917,7 +910,7 @@ report_fatal(Format, Args) ->
report_fatal(Format, Args, Core) ->
report_system_event({mnesia_fatal, Format, Args, Core}),
- catch exit(whereis(mnesia_monitor), fatal).
+ ?SAFE(exit(whereis(mnesia_monitor), fatal)).
%% We sleep longer and longer the more we try
%% Made some testing and came up with the following constants
@@ -930,8 +923,9 @@ random_time(Retries, _Counter0) ->
case get(random_seed) of
undefined ->
- {X, Y, Z} = erlang:now(), %% time()
- _ = random:seed(X, Y, Z),
+ _ = random:seed(erlang:unique_integer(),
+ erlang:monotonic_time(),
+ erlang:unique_integer()),
Time = Dup + random:uniform(MaxIntv),
%% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
Time;
@@ -1013,7 +1007,7 @@ dbg_out(Format, Args) ->
%% Keep the last 10 debug print outs
save(DbgInfo) ->
- catch save2(DbgInfo).
+ ?SAFE(save2(DbgInfo)).
save2(DbgInfo) ->
Key = {'$$$_report', current_pos},
@@ -1089,35 +1083,29 @@ db_match_object(Tab, Pat) ->
db_match_object(val({Tab, storage_type}), Tab, Pat).
db_match_object(Storage, Tab, Pat) ->
db_fixtable(Storage, Tab, true),
- Res = catch_match_object(Storage, Tab, Pat),
- db_fixtable(Storage, Tab, false),
- case Res of
- {'EXIT', Reason} -> exit(Reason);
- _ -> Res
+ try
+ case Storage of
+ disc_only_copies -> dets:match_object(Tab, Pat);
+ _ -> ets:match_object(Tab, Pat)
+ end
+ after
+ db_fixtable(Storage, Tab, false)
end.
-catch_match_object(disc_only_copies, Tab, Pat) ->
- catch dets:match_object(Tab, Pat);
-catch_match_object(_, Tab, Pat) ->
- catch ets:match_object(Tab, Pat).
-
db_select(Tab, Pat) ->
db_select(val({Tab, storage_type}), Tab, Pat).
db_select(Storage, Tab, Pat) ->
db_fixtable(Storage, Tab, true),
- Res = catch_select(Storage, Tab, Pat),
- db_fixtable(Storage, Tab, false),
- case Res of
- {'EXIT', Reason} -> exit(Reason);
- _ -> Res
+ try
+ case Storage of
+ disc_only_copies -> dets:select(Tab, Pat);
+ _ -> ets:select(Tab, Pat)
+ end
+ after
+ db_fixtable(Storage, Tab, false)
end.
-catch_select(disc_only_copies, Tab, Pat) ->
- catch dets:select(Tab, Pat);
-catch_select(_, Tab, Pat) ->
- catch ets:select(Tab, Pat).
-
db_select_init(disc_only_copies, Tab, Pat, Limit) ->
dets:select(Tab, Pat, Limit);
db_select_init(_, Tab, Pat, Limit) ->
@@ -1261,7 +1249,7 @@ dets_sync_open(Tab, Args) ->
end.
dets_sync_close(Tab) ->
- catch dets:close(Tab),
+ ?SAFE(dets:close(Tab)),
unlock_table(Tab),
ok.
@@ -1297,7 +1285,7 @@ readable_indecies(Tab) ->
scratch_debug_fun() ->
dbg_out("scratch_debug_fun(): ~p~n", [?DEBUG_TAB]),
- (catch ?ets_delete_table(?DEBUG_TAB)),
+ ?SAFE(?ets_delete_table(?DEBUG_TAB)),
?ets_new_table(?DEBUG_TAB, [set, public, named_table, {keypos, 2}]).
activate_debug_fun(FunId, Fun, InitialContext, File, Line) ->
@@ -1310,43 +1298,45 @@ activate_debug_fun(FunId, Fun, InitialContext, File, Line) ->
update_debug_info(Info).
update_debug_info(Info) ->
- case catch ?ets_insert(?DEBUG_TAB, Info) of
- {'EXIT', _} ->
+ try ?ets_insert(?DEBUG_TAB, Info),
+ ok
+ catch error:_ ->
scratch_debug_fun(),
- ?ets_insert(?DEBUG_TAB, Info);
- _ ->
- ok
+ ?ets_insert(?DEBUG_TAB, Info)
end,
dbg_out("update_debug_info(~p)~n", [Info]),
ok.
deactivate_debug_fun(FunId, _File, _Line) ->
- catch ?ets_delete(?DEBUG_TAB, FunId),
+ ?SAFE(?ets_delete(?DEBUG_TAB, FunId)),
ok.
eval_debug_fun(FunId, EvalContext, EvalFile, EvalLine) ->
- case catch ?ets_lookup(?DEBUG_TAB, FunId) of
- [] ->
- ok;
- [Info] ->
- OldContext = Info#debug_info.context,
- dbg_out("~s(~p): ~w "
- "activated in ~s(~p)~n "
- "eval_debug_fun(~w, ~w)~n",
- [filename:basename(EvalFile), EvalLine, Info#debug_info.id,
- filename:basename(Info#debug_info.file), Info#debug_info.line,
- OldContext, EvalContext]),
- Fun = Info#debug_info.function,
- NewContext = Fun(OldContext, EvalContext),
-
- case catch ?ets_lookup(?DEBUG_TAB, FunId) of
- [Info] when NewContext /= OldContext ->
- NewInfo = Info#debug_info{context = NewContext},
- update_debug_info(NewInfo);
- _ ->
- ok
- end;
- {'EXIT', _} -> ok
+ try
+ case ?ets_lookup(?DEBUG_TAB, FunId) of
+ [] ->
+ ok;
+ [Info] ->
+ OldContext = Info#debug_info.context,
+ dbg_out("~s(~p): ~w "
+ "activated in ~s(~p)~n "
+ "eval_debug_fun(~w, ~w)~n",
+ [filename:basename(EvalFile), EvalLine, Info#debug_info.id,
+ filename:basename(Info#debug_info.file), Info#debug_info.line,
+ OldContext, EvalContext]),
+ Fun = Info#debug_info.function,
+ NewContext = Fun(OldContext, EvalContext),
+
+ case ?ets_lookup(?DEBUG_TAB, FunId) of
+ [Info] when NewContext /= OldContext ->
+ NewInfo = Info#debug_info{context = NewContext},
+ update_debug_info(NewInfo);
+ _ ->
+ ok
+ end
+ end
+ catch error ->
+ ok
end.
-ifdef(debug).
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index 530317bcdd..65ea743fd3 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -35,7 +35,7 @@
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
Value -> Value
end.
@@ -69,9 +69,10 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
ignore;
_ ->
mnesia_monitor:mktab(Tab, Args),
- Count = mnesia_log:dcd2ets(Tab, Repair),
- case ets:info(Tab, size) of
- X when X < Count * 4 ->
+ _Count = mnesia_log:dcd2ets(Tab, Repair),
+ case mnesia_monitor:get_env(dump_disc_copies_at_startup)
+ andalso mnesia_dumper:needs_dump_ets(Tab) of
+ true ->
ok = mnesia_log:ets2dcd(Tab);
_ ->
ignore
@@ -331,7 +332,7 @@ wait_on_load_complete(Pid) ->
{Pid, Res} ->
Res;
{'EXIT', Pid, Reason} ->
- exit(Reason);
+ error(Reason);
Else ->
Pid ! Else,
wait_on_load_complete(Pid)
@@ -441,18 +442,18 @@ init_table(Tab, disc_only_copies, Fun, DetsInfo,Sender) ->
ErtsVer = erlang:system_info(version),
case DetsInfo of
{ErtsVer, DetsData} ->
- Res = (catch dets:is_compatible_bchunk_format(Tab, DetsData)),
- case Res of
- {'EXIT',{undef,[{dets,_,_,_}|_]}} ->
- Sender ! {self(), {old_protocol, Tab}},
- dets:init_table(Tab, Fun); %% Old dets version
- {'EXIT', What} ->
- exit(What);
+ try dets:is_compatible_bchunk_format(Tab, DetsData) of
false ->
Sender ! {self(), {old_protocol, Tab}},
dets:init_table(Tab, Fun); %% Old dets version
true ->
dets:init_table(Tab, Fun, [{format, bchunk}])
+ catch
+ error:{undef,[{dets,_,_,_}|_]} ->
+ Sender ! {self(), {old_protocol, Tab}},
+ dets:init_table(Tab, Fun); %% Old dets version
+ error:What ->
+ What
end;
Old when Old /= false ->
Sender ! {self(), {old_protocol, Tab}},
@@ -461,10 +462,10 @@ init_table(Tab, disc_only_copies, Fun, DetsInfo,Sender) ->
dets:init_table(Tab, Fun)
end;
init_table(Tab, _, Fun, _DetsInfo,_) ->
- case catch ets:init_table(Tab, Fun) of
- true ->
- ok;
- {'EXIT', Else} -> Else
+ try
+ true = ets:init_table(Tab, Fun),
+ ok
+ catch _:Else -> {Else, erlang:get_stacktrace()}
end.
@@ -571,9 +572,9 @@ handle_last({ram_copies, Tab}, _Type, DatBin) ->
down(Tab, Storage) ->
case Storage of
ram_copies ->
- catch ?ets_delete_table(Tab);
+ ?SAFE(?ets_delete_table(Tab));
disc_copies ->
- catch ?ets_delete_table(Tab);
+ ?SAFE(?ets_delete_table(Tab));
disc_only_copies ->
TmpFile = mnesia_lib:tab2tmp(Tab),
mnesia_lib:dets_sync_close(Tab),
@@ -657,26 +658,23 @@ send_table(Pid, Tab, RemoteS) ->
{Init, Chunk} = reader_funcs(UseDetsChunk, Tab, Storage, KeysPerTransfer),
SendIt = fun() ->
- prepare_copy(Pid, Tab, Storage),
+ {atomic, ok} = prepare_copy(Pid, Tab, Storage),
send_more(Pid, 1, Chunk, Init(), Tab),
finish_copy(Pid, Tab, Storage, RemoteS)
end,
- case catch SendIt() of
- receiver_died ->
+ try SendIt() of
+ {_, receiver_died} -> ok;
+ {atomic, no_more} -> ok
+ catch
+ throw:receiver_died ->
cleanup_tab_copier(Pid, Storage, Tab),
- unlink(whereis(mnesia_tm)),
ok;
- {_, receiver_died} ->
- unlink(whereis(mnesia_tm)),
- ok;
- {atomic, no_more} ->
- unlink(whereis(mnesia_tm)),
- ok;
- Reason ->
+ error:Reason -> %% Prepare failed
cleanup_tab_copier(Pid, Storage, Tab),
- unlink(whereis(mnesia_tm)),
- {error, Reason}
+ {error, {tab_copier, Tab, {Reason, erlang:get_stacktrace()}}}
+ after
+ unlink(whereis(mnesia_tm))
end
end.
@@ -689,12 +687,7 @@ prepare_copy(Pid, Tab, Storage) ->
mnesia_lib:db_fixtable(Storage, Tab, true),
ok
end,
- case mnesia:transaction(Trans) of
- {atomic, ok} ->
- ok;
- {aborted, Reason} ->
- exit({tab_copier_prepare, Tab, Reason})
- end.
+ mnesia:transaction(Trans).
update_where_to_write(Tab, Node) ->
case val({Tab, access_mode}) of
@@ -827,6 +820,6 @@ dat2bin(_Tab, _LocalS, _RemoteS) ->
nobin.
handle_exit(Pid, Reason) when node(Pid) == node() ->
- exit(Reason);
+ error(Reason);
handle_exit(_Pid, _Reason) -> %% Not from our node, this will be handled by
ignore. %% mnesia_down soon.
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index 1efb939e00..6658dbeacb 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -98,7 +98,7 @@ init(Parent) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
_VaLuE_ -> _VaLuE_
end.
@@ -1001,13 +1001,11 @@ flush_remaining(Ns=[Node | Tail], SkipNode, Res) ->
opt_lookup_in_client(lookup_in_client, Oid, Lock) ->
{Tab, Key} = Oid,
- case catch mnesia_lib:db_get(Tab, Key) of
- {'EXIT', _} ->
+ try mnesia_lib:db_get(Tab, Key)
+ catch error:_ ->
%% Table has been deleted from this node,
%% restart the transaction.
- #cyclic{op = read, lock = Lock, oid = Oid, lucky = nowhere};
- Val ->
- Val
+ #cyclic{op = read, lock = Lock, oid = Oid, lucky = nowhere}
end;
opt_lookup_in_client(Val, _Oid, _Lock) ->
Val.
@@ -1139,11 +1137,10 @@ send_requests([], _X) ->
rec_requests([Node | Nodes], Oid, Store) ->
Res = l_req_rec(Node, Store),
- case catch rlock_get_reply(Node, Store, Oid, Res) of
- {'EXIT', Reason} ->
- flush_remaining(Nodes, Node, Reason);
- _ ->
- rec_requests(Nodes, Oid, Store)
+ try rlock_get_reply(Node, Store, Oid, Res) of
+ _ -> rec_requests(Nodes, Oid, Store)
+ catch _:Reason ->
+ flush_remaining(Nodes, Node, Reason)
end;
rec_requests([], _Oid, _Store) ->
ok.
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index d2fd04a60b..21ad0ffdb6 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -200,7 +200,7 @@ log_header(Kind, Version) ->
log_kind=Kind,
mnesia_version=mnesia:system_info(version),
node=node(),
- now=now()}.
+ now=erlang:timestamp()}.
version() -> "4.3".
@@ -462,7 +462,7 @@ chunk_log(Cont) ->
chunk_log(_Log, eof) ->
eof;
chunk_log(Log, Cont) ->
- case catch disk_log:chunk(Log, Cont) of
+ case disk_log:chunk(Log, Cont) of
{error, Reason} ->
fatal("Possibly truncated ~p file: ~p~n",
[Log, Reason]);
@@ -647,11 +647,11 @@ backup_checkpoint(Name, Opaque, Args) when is_list(Args) ->
end.
check_backup_args([Arg | Tail], B) ->
- case catch check_backup_arg_type(Arg, B) of
- {'EXIT', _Reason} ->
- {error, {badarg, Arg}};
+ try check_backup_arg_type(Arg, B) of
B2 ->
check_backup_args(Tail, B2)
+ catch error:_ ->
+ {error, {badarg, Arg}}
end;
check_backup_args([], B) ->
@@ -674,11 +674,11 @@ check_backup_arg_type(Arg, B) ->
backup_master(ClientPid, B) ->
process_flag(trap_exit, true),
- case catch do_backup_master(B) of
- {'EXIT', Reason} ->
- ClientPid ! {self(), ClientPid, {error, {'EXIT', Reason}}};
+ try do_backup_master(B) of
Res ->
ClientPid ! {self(), ClientPid, Res}
+ catch _:Reason ->
+ ClientPid ! {self(), ClientPid, {error, {'EXIT', Reason}}}
end,
unlink(ClientPid),
exit(normal).
@@ -736,10 +736,10 @@ safe_apply(B, What, Args) ->
{'EXIT', Pid, R} -> Abort({'EXIT', Pid, R})
after 0 ->
Mod = B#backup_args.module,
- case catch apply(Mod, What, Args) of
+ try apply(Mod, What, Args) of
{ok, Opaque} -> B#backup_args{opaque=Opaque};
- {error, R} -> Abort(R);
- R -> Abort(R)
+ {error, R} -> Abort(R)
+ catch _:R -> Abort(R)
end
end.
@@ -748,10 +748,9 @@ abort_write(B, What, Args, Reason) ->
Opaque = B#backup_args.opaque,
dbg_out("Failed to perform backup. M=~p:F=~p:A=~p -> ~p~n",
[Mod, What, Args, Reason]),
- case catch apply(Mod, abort_write, [Opaque]) of
- {ok, _Res} ->
- throw({error, Reason});
- Other ->
+ try apply(Mod, abort_write, [Opaque]) of
+ {ok, _Res} -> throw({error, Reason})
+ catch _:Other ->
error("Failed to abort backup. ~p:~p~p -> ~p~n",
[Mod, abort_write, [Opaque], Other]),
throw({error, Reason})
@@ -892,10 +891,8 @@ tab_receiver(Pid, B, Tab, RecName, Slot) ->
end.
rec_filter(B, schema, _RecName, Recs) ->
- case catch mnesia_bup:refresh_cookie(Recs, B#backup_args.cookie) of
- Recs2 when is_list(Recs2) ->
- Recs2;
- {error, _Reason} ->
+ try mnesia_bup:refresh_cookie(Recs, B#backup_args.cookie)
+ catch throw:{error, _Reason} ->
%% No schema table cookie
Recs
end;
@@ -1006,13 +1003,14 @@ add_recs([{{Tab, _Key}, Val, delete_object} | Rest], N) ->
add_recs(Rest, N+1);
add_recs([{{Tab, Key}, Val, update_counter} | Rest], N) ->
{RecName, Incr} = Val,
- case catch ets:update_counter(Tab, Key, Incr) of
- CounterVal when is_integer(CounterVal) ->
- ok;
- _ when Incr < 0 ->
+ try
+ CounterVal = ets:update_counter(Tab, Key, Incr),
+ true = (CounterVal >= 0)
+ catch
+ error:_ when Incr < 0 ->
Zero = {RecName, Key, 0},
true = ets:insert(Tab, Zero);
- _ ->
+ error:_ ->
Zero = {RecName, Key, Incr},
true = ets:insert(Tab, Zero)
end,
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index 6fc1a394a6..14b1ab5c1a 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -268,7 +268,7 @@ init([Parent]) ->
set(version, Version),
dbg_out("Version: ~p~n", [Version]),
- case catch process_config_args(env()) of
+ try process_config_args(env()) of
ok ->
mnesia_lib:set({'$$$_report', current_pos}, 0),
Level = mnesia_lib:val(debug),
@@ -288,8 +288,8 @@ init([Parent]) ->
set(pending_checkpoints, []),
set(pending_checkpoint_pids, []),
- {ok, #state{supervisor = Parent}};
- {'EXIT', Reason} ->
+ {ok, #state{supervisor = Parent}}
+ catch _:Reason ->
mnesia_lib:report_fatal("Bad configuration: ~p~n", [Reason]),
{stop, {bad_config, Reason}}
end.
@@ -323,25 +323,24 @@ non_empty_dir() ->
%%----------------------------------------------------------------------
handle_call({mktab, Tab, Args}, _From, State) ->
- case catch ?ets_new_table(Tab, Args) of
- {'EXIT', ExitReason} ->
+ try ?ets_new_table(Tab, Args) of
+ Reply ->
+ {reply, Reply, State}
+ catch error:ExitReason ->
Msg = "Cannot create ets table",
Reason = {system_limit, Msg, Tab, Args, ExitReason},
fatal("~p~n", [Reason]),
- {noreply, State};
- Reply ->
- {reply, Reply, State}
+ {noreply, State}
end;
handle_call({unsafe_mktab, Tab, Args}, _From, State) ->
- case catch ?ets_new_table(Tab, Args) of
- {'EXIT', ExitReason} ->
- {reply, {error, ExitReason}, State};
+ try ?ets_new_table(Tab, Args) of
Reply ->
{reply, Reply, State}
+ catch error:ExitReason ->
+ {reply, {error, ExitReason}, State}
end;
-
handle_call({open_dets, Tab, Args}, _From, State) ->
case mnesia_lib:dets_sync_open(Tab, Args) of
{ok, Tab} ->
@@ -546,7 +545,7 @@ handle_info({'EXIT', Pid, fatal}, State) when node(Pid) == node() ->
%% is in progress
%% exit(State#state.supervisor, shutdown),
%% It is better to kill an innocent process
- catch exit(whereis(mnesia_locker), kill),
+ ?SAFE(exit(whereis(mnesia_locker), kill)),
{noreply, State};
handle_info(Msg = {'EXIT',Pid,_}, State) ->
@@ -664,6 +663,7 @@ env() ->
backup_module,
debug,
dir,
+ dump_disc_copies_at_startup,
dump_log_load_regulation,
dump_log_time_threshold,
dump_log_update_in_place,
@@ -692,6 +692,8 @@ default_env(debug) ->
default_env(dir) ->
Name = lists:concat(["Mnesia.", node()]),
filename:absname(Name);
+default_env(dump_disc_copies_at_startup) ->
+ true;
default_env(dump_log_load_regulation) ->
false;
default_env(dump_log_time_threshold) ->
@@ -724,11 +726,8 @@ default_env(send_compressed) ->
0.
check_type(Env, Val) ->
- case catch do_check_type(Env, Val) of
- {'EXIT', _Reason} ->
- exit({bad_config, Env, Val});
- NewVal ->
- NewVal
+ try do_check_type(Env, Val)
+ catch error:_ -> exit({bad_config, Env, Val})
end.
do_check_type(access_module, A) when is_atom(A) -> A;
@@ -741,6 +740,7 @@ do_check_type(debug, trace) -> trace;
do_check_type(debug, true) -> debug;
do_check_type(debug, verbose) -> verbose;
do_check_type(dir, V) -> filename:absname(V);
+do_check_type(dump_disc_copies_at_startup, B) -> bool(B);
do_check_type(dump_log_load_regulation, B) -> bool(B);
do_check_type(dump_log_time_threshold, I) when is_integer(I), I > 0 -> I;
do_check_type(dump_log_update_in_place, B) -> bool(B);
@@ -777,12 +777,12 @@ media(opt_disc) -> opt_disc;
media(ram) -> ram.
patch_env(Env, Val) ->
- case catch do_check_type(Env, Val) of
- {'EXIT', _Reason} ->
- {error, {bad_type, Env, Val}};
+ try do_check_type(Env, Val) of
NewVal ->
application_controller:set_env(mnesia, Env, NewVal),
NewVal
+ catch error:_ ->
+ {error, {bad_type, Env, Val}}
end.
detect_partitioned_network(Mon, Node) ->
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index eeb4fa0ced..aa567a23cb 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -178,11 +178,8 @@ log_decision(D) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} ->
- case mnesia_lib:other_val(Var) of
- error -> mnesia_lib:pr_other(Var, Reason);
- Val -> Val
- end;
+ {'EXIT', _Reason} ->
+ mnesia_lib:other_val(Var);
Value -> Value
end.
@@ -373,11 +370,8 @@ log_master_nodes2([], _UseDir, IsRunning, WorstRes) ->
get_master_node_info() ->
Tab = mnesia_decision,
Pat = {master_nodes, '_', '_'},
- case catch mnesia_lib:db_match_object(ram_copies,Tab, Pat) of
- {'EXIT', _} ->
- [];
- Masters ->
- Masters
+ try mnesia_lib:db_match_object(ram_copies,Tab, Pat)
+ catch error:_ -> []
end.
get_master_node_tables() ->
@@ -385,9 +379,8 @@ get_master_node_tables() ->
[Tab || {master_nodes, Tab, _Nodes} <- Masters].
get_master_nodes(Tab) ->
- case catch ?ets_lookup_element(mnesia_decision, Tab, 3) of
- {'EXIT', _} -> [];
- Nodes -> Nodes
+ try ?ets_lookup_element(mnesia_decision, Tab, 3)
+ catch error:_ -> []
end.
%% Determine what has happened to the transaction
@@ -485,8 +478,6 @@ load_decision_tab() ->
load_decision_tab(Cont, load_decision_tab),
mnesia_log:close_decision_tab().
-load_decision_tab(eof, _InitBy) ->
- ok;
load_decision_tab(Cont, InitBy) ->
case mnesia_log:chunk_decision_tab(Cont) of
{Cont2, Decisions} ->
@@ -519,8 +510,6 @@ dump_decision_log(InitBy) ->
Cont = mnesia_log:prepare_decision_log_dump(),
perform_dump_decision_log(Cont, InitBy).
-perform_dump_decision_log(eof, _InitBy) ->
- confirm_decision_log_dump();
perform_dump_decision_log(Cont, InitBy) when InitBy == startup ->
case mnesia_log:chunk_decision_log(Cont) of
{Cont2, Decisions} ->
@@ -1024,7 +1013,7 @@ decision(Tid) ->
decision(Tid, tabs()).
decision(Tid, [Tab | Tabs]) ->
- case catch ?ets_lookup(Tab, Tid) of
+ try ?ets_lookup(Tab, Tid) of
[D] when is_record(D, decision) ->
D;
[C] when is_record(C, transient_decision) ->
@@ -1034,8 +1023,8 @@ decision(Tid, [Tab | Tabs]) ->
ram_nodes = []
};
[] ->
- decision(Tid, Tabs);
- {'EXIT', _} ->
+ decision(Tid, Tabs)
+ catch error:_ ->
%% Recently switched transient decision table
decision(Tid, Tabs)
end;
@@ -1046,11 +1035,8 @@ outcome(Tid, Default) ->
outcome(Tid, Default, tabs()).
outcome(Tid, Default, [Tab | Tabs]) ->
- case catch ?ets_lookup_element(Tab, Tid, 3) of
- {'EXIT', _} ->
- outcome(Tid, Default, Tabs);
- Val ->
- Val
+ try ?ets_lookup_element(Tab, Tid, 3)
+ catch error:_ -> outcome(Tid, Default, Tabs)
end;
outcome(_Tid, Default, []) ->
Default.
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index 6e43052fb0..4c8234bbc7 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -151,7 +151,7 @@ exit_on_error(GoodRes) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
Value -> Value
end.
@@ -262,7 +262,7 @@ incr_version(Cs) ->
[] -> {Major + 1, 0}; % All replicas are active
_ -> {Major, Minor + 1} % Some replicas are inactive
end,
- Cs#cstruct{version = {V, {node(), now()}}}.
+ Cs#cstruct{version = {V, {node(), erlang:timestamp()}}}.
%% Returns table name
insert_cstruct(Tid, Cs, KeepWhereabouts) ->
@@ -2151,14 +2151,14 @@ prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
mnesia_lib:db_fixtable(Storage, Tab, true),
Key = mnesia_lib:db_first(Tab),
Op = {op, transform, Fun, TabDef},
- case catch transform_objs(Fun, Tab, RecName,
- Key, NewArity, Storage, Type, [Op]) of
- {'EXIT', Reason} ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- exit({"Bad transform function", Tab, Fun, node(), Reason});
+ try transform_objs(Fun, Tab, RecName, Key,
+ NewArity, Storage, Type, [Op]) of
Objs ->
mnesia_lib:db_fixtable(Storage, Tab, false),
{true, Objs, mandatory}
+ catch _:Reason ->
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ exit({"Bad transform function", Tab, Fun, node(), Reason})
end
end;
@@ -2342,7 +2342,7 @@ undo_prepare_commit(Tid, Commit) ->
ignore;
Ops ->
%% Catch to allow failure mnesia_controller may not be started
- catch mnesia_controller:release_schema_commit_lock(),
+ ?SAFE(mnesia_controller:release_schema_commit_lock()),
undo_prepare_ops(Tid, Ops)
end,
Commit.
@@ -2489,14 +2489,14 @@ ram_delete_table(Tab, Storage) ->
%% delete possible index files and data .....
%% Got to catch this since if no info has been set in the
%% mnesia_gvar it will crash
- catch mnesia_index:del_transient(Tab, Storage),
+ ?CATCH(mnesia_index:del_transient(Tab, Storage)),
case ?catch_val({Tab, {index, snmp}}) of
{'EXIT', _} ->
ignore;
Etab ->
- catch mnesia_snmp_hook:delete_table(Tab, Etab)
+ ?SAFE(mnesia_snmp_hook:delete_table(Tab, Etab))
end,
- catch ?ets_delete_table(Tab)
+ ?SAFE(?ets_delete_table(Tab))
end.
purge_dir(Dir, KeepFiles) ->
@@ -2584,10 +2584,7 @@ info2(_, []) ->
io:format("~n", []).
get_table_properties(Tab) ->
- case catch mnesia_lib:db_match_object(ram_copies,
- mnesia_gvar, {{Tab, '_'}, '_'}) of
- {'EXIT', _} ->
- mnesia:abort({no_exists, Tab, all});
+ try mnesia_lib:db_match_object(ram_copies, mnesia_gvar, {{Tab, '_'}, '_'}) of
RawGvar ->
case [{Item, Val} || {{_Tab, Item}, Val} <- RawGvar] of
[] ->
@@ -2598,6 +2595,8 @@ get_table_properties(Tab) ->
Master = {master_nodes, mnesia:table_info(Tab, master_nodes)},
lists:sort([Size, Memory, Master | Gvar])
end
+ catch error:_ ->
+ mnesia:abort({no_exists, Tab, all})
end.
%%%%%%%%%%% RESTORE %%%%%%%%%%%
@@ -2620,15 +2619,15 @@ restore(_Opaque, BadArg) ->
{aborted, {badarg, BadArg}}.
restore(Opaque, Args, Module) when is_list(Args), is_atom(Module) ->
InitR = #r{opaque = Opaque, module = Module},
- case catch lists:foldl(fun check_restore_arg/2, InitR, Args) of
+ try lists:foldl(fun check_restore_arg/2, InitR, Args) of
R when is_record(R, r) ->
case mnesia_bup:read_schema(R#r.module, Opaque) of
{error, Reason} ->
{aborted, Reason};
BupSchema ->
schema_transaction(fun() -> do_restore(R, BupSchema) end)
- end;
- {'EXIT', Reason} ->
+ end
+ catch exit:Reason ->
{aborted, Reason}
end;
restore(_Opaque, Args, Module) ->
@@ -3073,15 +3072,13 @@ do_make_merge_schema(Node, NeedsConv, RemoteCs = #cstruct{}) ->
%% Returns a new cstruct or issues a fatal error
merge_cstructs(Cs, RemoteCs, Force) ->
verify_cstruct(Cs),
- case catch do_merge_cstructs(Cs, RemoteCs, Force) of
- {'EXIT', {aborted, _Reason}} when Force == true ->
- Cs;
- {'EXIT', Reason} ->
- exit(Reason);
+ try do_merge_cstructs(Cs, RemoteCs, Force) of
MergedCs when is_record(MergedCs, cstruct) ->
- MergedCs;
- Other ->
- throw(Other)
+ MergedCs
+ catch exit:{aborted, _Reason} when Force == true ->
+ Cs;
+ exit:Reason -> exit(Reason);
+ error:Reason -> exit(Reason)
end.
do_merge_cstructs(Cs, RemoteCs, Force) ->
diff --git a/lib/mnesia/src/mnesia_snmp_hook.erl b/lib/mnesia/src/mnesia_snmp_hook.erl
index 256f83b029..c76cf89ebb 100644
--- a/lib/mnesia/src/mnesia_snmp_hook.erl
+++ b/lib/mnesia/src/mnesia_snmp_hook.erl
@@ -30,15 +30,6 @@
-include("mnesia.hrl").
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} ->
- case mnesia_lib:other_val(Var) of
- error -> mnesia_lib:pr_other(Var, _ReASoN_);
- Val -> Val
- end;
- _VaLuE_ -> _VaLuE_
- end.
check_ustruct([]) ->
true; %% default value, not SNMP'ified
@@ -85,12 +76,12 @@ delete_table(_MnesiaTab, Tree) ->
%%-----------------------------------------------------------------
update({clear_table, MnesiaTab}) ->
- Tree = val({MnesiaTab, {index, snmp}}),
+ Tree = mnesia_lib:val({MnesiaTab, {index, snmp}}),
b_clear(Tree),
ok;
update({Op, MnesiaTab, MnesiaKey, SnmpKey}) ->
- Tree = val({MnesiaTab, {index, snmp}}),
+ Tree = mnesia_lib:val({MnesiaTab, {index, snmp}}),
update(Op, Tree, MnesiaKey, SnmpKey).
update(Op, Tree, MnesiaKey, SnmpKey) ->
@@ -120,7 +111,7 @@ update(Op, Tree, MnesiaKey, SnmpKey) ->
%%-----------------------------------------------------------------
key_to_oid(Tab,Key) ->
- Types = val({Tab,snmp}),
+ Types = mnesia_lib:val({Tab,snmp}),
key_to_oid(Tab, Key, Types).
key_to_oid(Tab, Key, [{key, Types}]) ->
@@ -144,7 +135,7 @@ keys_to_oid(N, Key, Oid, Types) ->
%% This can be lookup up in tree but that might be on a remote node.
%% It's probably faster to look it up, but use when it migth be remote
oid_to_key(Oid, Tab) ->
- [{key, Types}] = val({Tab,snmp}),
+ [{key, Types}] = mnesia_lib:val({Tab,snmp}),
oid_to_key_1(Types, Oid).
oid_to_key_1(integer, [Key]) -> Key;
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index 866a57e370..c39edea9e3 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -186,11 +186,11 @@ patch_record(Tab, Obj) ->
end.
what(Tab, Tid, {RecName, Key}, delete, undefined) ->
- case catch mnesia_lib:db_get(Tab, Key) of
- Old when is_list(Old) -> %% Op only allowed for set table.
- {mnesia_table_event, {delete, Tab, {RecName, Key}, Old, Tid}};
- _ ->
- %% Record just deleted by a dirty_op or
+ try mnesia_lib:db_get(Tab, Key) of
+ Old -> %% Op only allowed for set table.
+ {mnesia_table_event, {delete, Tab, {RecName, Key}, Old, Tid}}
+ catch error:_ ->
+ %% Record just deleted by a dirty_op or
%% the whole table has been deleted
ignore
end;
@@ -199,10 +199,10 @@ what(Tab, Tid, Obj, delete, Old) ->
what(Tab, Tid, Obj, delete_object, _Old) ->
{mnesia_table_event, {delete, Tab, Obj, [Obj], Tid}};
what(Tab, Tid, Obj, write, undefined) ->
- case catch mnesia_lib:db_get(Tab, element(2, Obj)) of
- Old when is_list(Old) ->
- {mnesia_table_event, {write, Tab, Obj, Old, Tid}};
- {'EXIT', _} ->
+ try mnesia_lib:db_get(Tab, element(2, Obj)) of
+ Old ->
+ {mnesia_table_event, {write, Tab, Obj, Old, Tid}}
+ catch error:_ ->
ignore
end;
what(Tab, Tid, Obj, write, Old) ->
@@ -386,12 +386,12 @@ activate(ClientPid, What, Var, OldSubscribers, SubscrTab) ->
case lists:member(ClientPid, Old) of
false ->
%% Don't care about checking old links
- case catch link(ClientPid) of
+ try link(ClientPid) of
true ->
?ets_insert(SubscrTab, {ClientPid, What}),
add_subscr(Var, What, ClientPid),
- {ok, node()};
- {'EXIT', _Reason} ->
+ {ok, node()}
+ catch error:_ ->
{error, {no_exists, ClientPid}}
end;
true ->
@@ -443,11 +443,10 @@ add_subscr({Tab, commit_work}, What, Pid) ->
deactivate(ClientPid, What, Var, SubscrTab) ->
?ets_match_delete(SubscrTab, {ClientPid, What}),
- case catch ?ets_lookup_element(SubscrTab, ClientPid, 1) of
- List when is_list(List) ->
- ignore;
- {'EXIT', _} ->
- unlink(ClientPid)
+ try
+ ?ets_lookup_element(SubscrTab, ClientPid, 1),
+ ignore
+ catch error:_ -> unlink(ClientPid)
end,
try
del_subscr(Var, What, ClientPid),
diff --git a/lib/mnesia/src/mnesia_text.erl b/lib/mnesia/src/mnesia_text.erl
index 0906d18da9..794e633238 100644
--- a/lib/mnesia/src/mnesia_text.erl
+++ b/lib/mnesia/src/mnesia_text.erl
@@ -84,8 +84,12 @@ validate_tab({Tabname, RecName, List}) ->
validate_tab(_) -> error(badtab).
make_tabs([{Tab, Def} | Tail]) ->
- case catch mnesia:table_info(Tab, where_to_read) of
- {'EXIT', _} -> %% non-existing table
+ try mnesia:table_info(Tab, where_to_read) of
+ Node ->
+ io:format("** Table ~w already exists on ~p, just entering data~n",
+ [Tab, Node]),
+ make_tabs(Tail)
+ catch exit:_ -> %% non-existing table
case mnesia:create_table(Tab, Def) of
{aborted, Reason} ->
io:format("** Failed to create table ~w ~n"
@@ -95,11 +99,7 @@ make_tabs([{Tab, Def} | Tail]) ->
_ ->
io:format("New table ~w~n", [Tab]),
make_tabs(Tail)
- end;
- Node ->
- io:format("** Table ~w already exists on ~p, just entering data~n",
- [Tab, Node]),
- make_tabs(Tail)
+ end
end;
make_tabs([]) ->
@@ -118,11 +118,9 @@ load_data(L) ->
parse(File) ->
case file(File) of
{ok, Terms} ->
- case catch collect(Terms) of
- {error, X} ->
- {error, X};
- Other ->
- {ok, Other}
+ try collect(Terms) of
+ Other -> {ok, Other}
+ catch throw:Error -> Error
end;
Other ->
Other
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index af658150da..b4b46228e9 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -51,6 +51,7 @@
]).
-include("mnesia.hrl").
+
-import(mnesia_lib, [set/2]).
-import(mnesia_lib, [fatal/2, verbose/2, dbg_out/2]).
@@ -119,7 +120,7 @@ init(Parent) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
+ {'EXIT', _} -> mnesia_lib:other_val(Var);
_VaLuE_ -> _VaLuE_
end.
@@ -224,11 +225,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
end;
{From, start_outer} -> %% Create and associate ets_tab with Tid
- case catch ?ets_new_table(mnesia_trans_store, [bag, public]) of
- {'EXIT', Reason} -> %% system limit
- Msg = "Cannot create an ets table for the "
- "local transaction store",
- reply(From, {error, {system_limit, Msg, Reason}}, State);
+ try ?ets_new_table(mnesia_trans_store, [bag, public]) of
Etab ->
tmlink(From),
C = mnesia_recover:incr_trans_tid_serial(),
@@ -237,6 +234,10 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
A2 = gb_trees:insert(Tid,[Etab],Coordinators),
S2 = State#state{coordinators = A2},
reply(From, {new_tid, Tid, Etab}, S2)
+ catch error:Reason -> %% system limit
+ Msg = "Cannot create an ets table for the "
+ "local transaction store",
+ reply(From, {error, {system_limit, Msg, Reason}}, State)
end;
{From, {ask_commit, Protocol, Tid, Commit, DiscNs, RamNs}} ->
@@ -339,15 +340,15 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
end;
{From, {add_store, Tid}} -> %% new store for nested transaction
- case catch ?ets_new_table(mnesia_trans_store, [bag, public]) of
- {'EXIT', Reason} -> %% system limit
- Msg = "Cannot create an ets table for a nested "
- "local transaction store",
- reply(From, {error, {system_limit, Msg, Reason}}, State);
+ try ?ets_new_table(mnesia_trans_store, [bag, public]) of
Etab ->
A2 = add_coord_store(Coordinators, Tid, Etab),
reply(From, {new_store, Etab},
State#state{coordinators = A2})
+ catch error:Reason -> %% system limit
+ Msg = "Cannot create an ets table for a nested "
+ "local transaction store",
+ reply(From, {error, {system_limit, Msg, Reason}}, State)
end;
{From, {del_store, Tid, Current, Obsolete, PropagateStore}} ->
@@ -471,13 +472,13 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
do_sync_dirty(From, Tid, Commit, _Tab) ->
?eval_debug_fun({?MODULE, sync_dirty, pre}, [{tid, Tid}]),
- Res = (catch do_dirty(Tid, Commit)),
+ Res = do_dirty(Tid, Commit),
?eval_debug_fun({?MODULE, sync_dirty, post}, [{tid, Tid}]),
From ! {?MODULE, node(), {dirty_res, Res}}.
do_async_dirty(Tid, Commit, _Tab) ->
?eval_debug_fun({?MODULE, async_dirty, pre}, [{tid, Tid}]),
- catch do_dirty(Tid, Commit),
+ do_dirty(Tid, Commit),
?eval_debug_fun({?MODULE, async_dirty, post}, [{tid, Tid}]).
@@ -501,7 +502,7 @@ process_dirty_queue(_Tab, []) ->
[].
prepare_pending_coordinators([{Tid, [Store | _Etabs]} | Coords], IgnoreNew) ->
- case catch ?ets_lookup(Store, pending) of
+ try ?ets_lookup(Store, pending) of
[] ->
prepare_pending_coordinators(Coords, IgnoreNew);
[Pending] ->
@@ -511,8 +512,8 @@ prepare_pending_coordinators([{Tid, [Store | _Etabs]} | Coords], IgnoreNew) ->
true ->
ignore
end,
- prepare_pending_coordinators(Coords, IgnoreNew);
- {'EXIT', _} ->
+ prepare_pending_coordinators(Coords, IgnoreNew)
+ catch error:_ ->
prepare_pending_coordinators(Coords, IgnoreNew)
end;
prepare_pending_coordinators([], _IgnoreNew) ->
@@ -573,11 +574,7 @@ recover_coordinator(Tid, Etabs) ->
Store = hd(Etabs),
CheckNodes = get_elements(nodes,Store),
TellNodes = CheckNodes -- [node()],
- case catch arrange(Tid, Store, async) of
- {'EXIT', Reason} ->
- dbg_out("Recovery of coordinator ~p failed:~n", [Tid, Reason]),
- Protocol = asym_trans,
- tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes);
+ try arrange(Tid, Store, async) of
{_N, Prep} ->
%% Tell the participants about the outcome
Protocol = Prep#prep.protocol,
@@ -596,6 +593,11 @@ recover_coordinator(Tid, Etabs) ->
false -> %% When killed before store havn't been copied to
ok %% to the new nested trans store.
end
+ catch _:Reason ->
+ dbg_out("Recovery of coordinator ~p failed:~n",
+ [Tid, {Reason, erlang:get_stacktrace()}]),
+ Protocol = asym_trans,
+ tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes)
end,
erase_ets_tabs(Etabs),
transaction_terminated(Tid),
@@ -724,33 +726,25 @@ non_transaction(OldState={_,_,Trans}, Fun, Args, ActivityKind, Mod)
_ -> async
end,
case transaction(OldState, Fun, Args, infinity, Mod, Kind) of
- {atomic, Res} ->
- Res;
- {aborted,Res} ->
- exit(Res)
+ {atomic, Res} -> Res;
+ {aborted,Res} -> exit(Res)
end;
non_transaction(OldState, Fun, Args, ActivityKind, Mod) ->
Id = {ActivityKind, self()},
NewState = {Mod, Id, non_transaction},
put(mnesia_activity_state, NewState),
- %% I Want something uniqe here, references are expensive
- Ref = mNeSia_nOn_TrAnSacTioN,
- RefRes = (catch {Ref, apply(Fun, Args)}),
- case OldState of
- undefined -> erase(mnesia_activity_state);
- _ -> put(mnesia_activity_state, OldState)
- end,
- case RefRes of
- {Ref, Res} ->
- case Res of
- {'EXIT', Reason} -> exit(Reason);
- {aborted, Reason} -> mnesia:abort(Reason);
- _ -> Res
- end;
- {'EXIT', Reason} ->
- exit(Reason);
- Throw ->
- throw(Throw)
+ try apply(Fun, Args) of
+ {'EXIT', Reason} -> exit(Reason);
+ {aborted, Reason} -> mnesia:abort(Reason);
+ Res -> Res
+ catch
+ throw:Throw -> throw(Throw);
+ _:Reason -> exit(Reason)
+ after
+ case OldState of
+ undefined -> erase(mnesia_activity_state);
+ _ -> put(mnesia_activity_state, OldState)
+ end
end.
transaction(OldTidTs, Fun, Args, Retries, Mod, Type) ->
@@ -810,23 +804,28 @@ insert_objs([], _Tab) ->
ok.
execute_transaction(Fun, Args, Factor, Retries, Type) ->
- case catch apply_fun(Fun, Args, Type) of
- {'EXIT', Reason} ->
- check_exit(Fun, Args, Factor, Retries, Reason, Type);
+ try apply_fun(Fun, Args, Type) of
{atomic, Value} ->
mnesia_lib:incr_counter(trans_commits),
erase(mnesia_activity_state),
%% no need to clear locks, already done by commit ...
%% Flush any un processed mnesia_down messages we might have
flush_downs(),
- catch unlink(whereis(?MODULE)),
+ ?SAFE(unlink(whereis(?MODULE))),
{atomic, Value};
+ {do_abort, Reason} ->
+ check_exit(Fun, Args, Factor, Retries, {aborted, Reason}, Type);
{nested_atomic, Value} ->
mnesia_lib:incr_counter(trans_commits),
- {atomic, Value};
- Value -> %% User called throw
+ {atomic, Value}
+ catch throw:Value -> %% User called throw
Reason = {aborted, {throw, Value}},
- return_abort(Fun, Args, Reason)
+ return_abort(Fun, Args, Reason);
+ error:Reason ->
+ ST = erlang:get_stacktrace(),
+ check_exit(Fun, Args, Factor, Retries, {Reason,ST}, Type);
+ _:Reason ->
+ check_exit(Fun, Args, Factor, Retries, Reason, Type)
end.
apply_fun(Fun, Args, Type) ->
@@ -836,10 +835,10 @@ apply_fun(Fun, Args, Type) ->
{atomic, Result};
do_commit_nested ->
{nested_atomic, Result};
- {do_abort, {aborted, Reason}} ->
- {'EXIT', {aborted, Reason}};
- {do_abort, Reason} ->
- {'EXIT', {aborted, Reason}}
+ {do_abort, {aborted, Reason}} ->
+ {do_abort, Reason};
+ {do_abort, _} = Abort ->
+ Abort
end.
check_exit(Fun, Args, Factor, Retries, Reason, Type) ->
@@ -943,7 +942,7 @@ return_abort(Fun, Args, Reason) ->
OldStore = Ts#tidstore.store,
Nodes = get_elements(nodes, OldStore),
intercept_friends(Tid, Ts),
- catch mnesia_lib:incr_counter(trans_failures),
+ ?SAFE(mnesia_lib:incr_counter(trans_failures)),
Level = Ts#tidstore.level,
if
Level == 1 ->
@@ -951,7 +950,7 @@ return_abort(Fun, Args, Reason) ->
?MODULE ! {delete_transaction, Tid},
erase(mnesia_activity_state),
flush_downs(),
- catch unlink(whereis(?MODULE)),
+ ?SAFE(unlink(whereis(?MODULE))),
{aborted, mnesia_lib:fix_error(Reason)};
true ->
%% Nested transaction
@@ -1005,11 +1004,11 @@ erase_activity_id() ->
erase(mnesia_activity_state).
get_elements(Type,Store) ->
- case catch ?ets_lookup(Store, Type) of
+ try ?ets_lookup(Store, Type) of
[] -> [];
[{_,Val}] -> [Val];
- {'EXIT', _} -> [];
Vals -> [Val|| {_,Val} <- Vals]
+ catch error:_ -> []
end.
opt_propagate_store(_Current, _Obsolete, false) ->
@@ -1032,7 +1031,7 @@ intercept_friends(_Tid, Ts) ->
intercept_best_friend([],_) -> ok;
intercept_best_friend([{stop,Fun} | R],Ignore) ->
- catch Fun(),
+ ?CATCH(Fun()),
intercept_best_friend(R,Ignore);
intercept_best_friend([Pid | R],false) ->
Pid ! {activity_ended, undefined, self()},
@@ -1046,25 +1045,12 @@ wait_for_best_friend(Pid, Timeout) ->
{'EXIT', Pid, _} -> ok;
{activity_ended, _, Pid} -> ok
after Timeout ->
- case my_process_is_alive(Pid) of
+ case erlang:is_process_alive(Pid) of
true -> wait_for_best_friend(Pid, 1000);
false -> ok
end
end.
-my_process_is_alive(Pid) ->
- case catch erlang:is_process_alive(Pid) of % New BIF in R5
- true ->
- true;
- false ->
- false;
- {'EXIT', _} -> % Pre R5 backward compatibility
- case process_info(Pid, message_queue_len) of
- undefined -> false;
- _ -> true
- end
- end.
-
dirty(Protocol, Item) ->
{{Tab, Key}, _Val, _Op} = Item,
Tid = {dirty, self()},
@@ -1144,18 +1130,8 @@ arrange(Tid, Store, Type) ->
async -> #prep{protocol = sym_trans, records = Recs};
sync -> #prep{protocol = sync_sym_trans, records = Recs}
end,
- case catch do_arrange(Tid, Store, Key, Prep, N) of
- {'EXIT', Reason} ->
- dbg_out("do_arrange failed ~p ~p~n", [Reason, Tid]),
- case Reason of
- {aborted, R} ->
- mnesia:abort(R);
- _ ->
- mnesia:abort(Reason)
- end;
- {New, Prepared} ->
- {New, Prepared#prep{records = reverse(Prepared#prep.records)}}
- end.
+ {New, Prepared} = do_arrange(Tid, Store, Key, Prep, N),
+ {New, Prepared#prep{records = reverse(Prepared#prep.records)}}.
reverse([]) ->
[];
@@ -1522,7 +1498,7 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
?ets_insert(Store, Pending),
{WaitFor, Local} = ask_commit(asym_trans, Tid, CR2, DiscNs, RamNs),
- SchemaPrep = (catch mnesia_schema:prepare_commit(Tid, Local, {coord, WaitFor})),
+ SchemaPrep = ?CATCH(mnesia_schema:prepare_commit(Tid, Local, {coord, WaitFor})),
{Votes, Pids} = rec_all(WaitFor, Tid, do_commit, []),
?eval_debug_fun({?MODULE, multi_commit_asym_got_votes},
@@ -1589,7 +1565,7 @@ rec_acc_pre_commit([Pid | Tail], Tid, Store, Commit, Res, DumperMode,
GoodPids, SchemaAckPids);
{mnesia_down, Node} when Node == node(Pid) ->
AbortRes = {do_abort, {bad_commit, Node}},
- catch Pid ! {Tid, AbortRes}, %% Tell him that he has died
+ ?SAFE(Pid ! {Tid, AbortRes}), %% Tell him that he has died
rec_acc_pre_commit(Tail, Tid, Store, Commit, AbortRes, DumperMode,
GoodPids, SchemaAckPids)
end;
@@ -1666,7 +1642,7 @@ commit_participant(Coord, Tid, C = #commit{}, DiscNs, RamNs) ->
commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?eval_debug_fun({?MODULE, commit_participant, pre}, [{tid, Tid}]),
- case catch mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
+ try mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
{Modified, C = #commit{}, DumperMode} ->
%% If we can not find any local unclear decision
%% we should presume abort at startup recovery
@@ -1742,9 +1718,8 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
reply(Coord, {do_abort, Tid, self(), {bad_commit,internal}}),
verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
[Tid, Msg])
- end;
-
- {'EXIT', Reason} ->
+ end
+ catch _:Reason ->
?eval_debug_fun({?MODULE, commit_participant, vote_no},
[{tid, Tid}]),
reply(Coord, {vote_no, Tid, Reason}),
@@ -1790,22 +1765,20 @@ do_commit(Tid, C, DumperMode) ->
%% Update the items
do_update(Tid, Storage, [Op | Ops], OldRes) ->
- case catch do_update_op(Tid, Storage, Op) of
- ok ->
- do_update(Tid, Storage, Ops, OldRes);
- {'EXIT', Reason} ->
+ try do_update_op(Tid, Storage, Op) of
+ ok -> do_update(Tid, Storage, Ops, OldRes);
+ NewRes -> do_update(Tid, Storage, Ops, NewRes)
+ catch _:Reason ->
%% This may only happen when we recently have
%% deleted our local replica, changed storage_type
%% or transformed table
%% BUGBUG: Updates may be lost if storage_type is changed.
%% Determine actual storage type and try again.
%% BUGBUG: Updates may be lost if table is transformed.
-
+ ST = erlang:get_stacktrace(),
verbose("do_update in ~w failed: ~p -> {'EXIT', ~p}~n",
- [Tid, Op, Reason]),
- do_update(Tid, Storage, Ops, OldRes);
- NewRes ->
- do_update(Tid, Storage, Ops, NewRes)
+ [Tid, Op, {Reason, ST}]),
+ do_update(Tid, Storage, Ops, OldRes)
end;
do_update(_Tid, _Storage, [], Res) ->
Res.
@@ -1821,14 +1794,15 @@ do_update_op(Tid, Storage, {{Tab, K}, Val, delete}) ->
do_update_op(Tid, Storage, {{Tab, K}, {RecName, Incr}, update_counter}) ->
{NewObj, OldObjs} =
- case catch mnesia_lib:db_update_counter(Storage, Tab, K, Incr) of
- NewVal when is_integer(NewVal), NewVal >= 0 ->
- {{RecName, K, NewVal}, [{RecName, K, NewVal - Incr}]};
- _ when Incr > 0 ->
+ try
+ NewVal = mnesia_lib:db_update_counter(Storage, Tab, K, Incr),
+ true = is_integer(NewVal) andalso (NewVal >= 0),
+ {{RecName, K, NewVal}, [{RecName, K, NewVal - Incr}]}
+ catch error:_ when Incr > 0 ->
New = {RecName, K, Incr},
mnesia_lib:db_put(Storage, Tab, New),
{New, []};
- _ ->
+ error:_ ->
Zero = {RecName, K, 0},
mnesia_lib:db_put(Storage, Tab, Zero),
{Zero, []}
@@ -1913,16 +1887,14 @@ commit_clear([H|R], Tid, Tab, K, Obj)
do_snmp(_, []) -> ok;
do_snmp(Tid, [Head | Tail]) ->
- case catch mnesia_snmp_hook:update(Head) of
- {'EXIT', Reason} ->
+ try mnesia_snmp_hook:update(Head)
+ catch _:Reason ->
%% This should only happen when we recently have
%% deleted our local replica or recently deattached
%% the snmp table
-
+ ST = erlang:get_stacktrace(),
verbose("do_snmp in ~w failed: ~p -> {'EXIT', ~p}~n",
- [Tid, Head, Reason]);
- ok ->
- ignore
+ [Tid, Head, {Reason, ST}])
end,
do_snmp(Tid, Tail).
@@ -2093,7 +2065,7 @@ rec_all([Node | Tail], Tid, Res, Pids) ->
%% Make sure that mnesia_tm knows it has died
%% it may have been restarted
Abort = {do_abort, {bad_commit, Node}},
- catch {?MODULE, Node} ! {Tid, Abort},
+ ?SAFE({?MODULE, Node} ! {Tid, Abort}),
rec_all(Tail, Tid, Abort, Pids)
end;
rec_all([], _Tid, Res, Pids) ->
diff --git a/lib/mnesia/test/mnesia_config_backup.erl b/lib/mnesia/test/mnesia_config_backup.erl
index 0916e255e2..a7d8c04a45 100644
--- a/lib/mnesia/test/mnesia_config_backup.erl
+++ b/lib/mnesia/test/mnesia_config_backup.erl
@@ -90,7 +90,8 @@ open_read(Name) ->
List = lists:reverse(ReverseList),
{ok, #backup{name = Name, mode = read, items = List}};
{error, Reason} ->
- {error, {open_read, Reason}}
+ %% {error, {open_read, Reason}}
+ {Reason, error} %% Testing error handling in mnesia
end.
read(Opaque) when Opaque#backup.mode == read ->
diff --git a/lib/mnesia/test/mnesia_config_test.erl b/lib/mnesia/test/mnesia_config_test.erl
index c495bce63f..a8fb93b28e 100644
--- a/lib/mnesia/test/mnesia_config_test.erl
+++ b/lib/mnesia/test/mnesia_config_test.erl
@@ -37,7 +37,6 @@
dump_log_update_in_place/1,
event_module/1,
- ignore_fallback_at_startup/1,
inconsistent_database/1,
max_wait_for_decision/1,
send_compressed/1,
@@ -104,7 +103,7 @@ all() ->
[access_module, auto_repair, backup_module, debug, dir,
dump_log_load_regulation, {group, dump_log_thresholds},
dump_log_update_in_place,
- event_module, ignore_fallback_at_startup,
+ event_module,
inconsistent_database, max_wait_for_decision,
send_compressed, app_test, {group, schema_config},
unknown_config].
@@ -317,11 +316,17 @@ backup_module(Config) when is_list(Config) ->
?match([], mnesia_test_lib:start_mnesia(Nodes, [test_table, test_table2])),
%% Now check newly started tables
- ?match({atomic, [1,2]},
+ ?match({atomic, [1,2]},
mnesia:transaction(fun() -> lists:sort(mnesia:all_keys(test_table)) end)),
- ?match({atomic, [3,4]},
+ ?match({atomic, [3,4]},
mnesia:transaction(fun() -> lists:sort(mnesia:all_keys(test_table2)) end)),
-
+
+ %% Test some error cases
+ mnesia:set_debug_level(debug),
+ ?match({error, _}, mnesia:install_fallback("NonExisting.FILE")),
+ ?match({error, _}, mnesia:install_fallback(filename:join(mnesia_lib:dir(), "LATEST.LOG"))),
+
+ %% Cleanup
file:delete(File),
?verify_mnesia(Nodes, []),
?cleanup(1, Config),
@@ -609,13 +614,6 @@ dump_log_load_regulation(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-ignore_fallback_at_startup(doc) ->
- ["Start Mnesia without rollback of the database to the fallback. ",
- "Once Mnesia has been (re)started the installed fallback should",
- "be handled as a normal active fallback.",
- "Install a customized event module which disables the termination",
- "of Mnesia when mnesia_down occurrs with an active fallback."].
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
max_wait_for_decision(doc) ->
diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl
index 9e0a8db1ae..68efa3f6ea 100644
--- a/lib/mnesia/test/mnesia_evil_backup.erl
+++ b/lib/mnesia/test/mnesia_evil_backup.erl
@@ -142,6 +142,9 @@ restore_errors(Config) when is_list(Config) ->
?match({aborted, {badarg, _}}, mnesia:restore(notAfile, [{skip_tables, xxx}])),
?match({aborted, {badarg, _}}, mnesia:restore(notAfile, [{recreate_tables, [schema]}])),
?match({aborted, {badarg, _}}, mnesia:restore(notAfile, [{default_op, asdklasd}])),
+ MnesiaDir = mnesia_lib:dir(),
+ ?match({aborted, {not_a_log_file, _}}, mnesia:restore(filename:join(MnesiaDir, "schema.DAT"), [])),
+ ?match({aborted, _}, mnesia:restore(filename:join(MnesiaDir, "LATEST.LOG"), [])),
ok.
restore_clear(suite) -> [];
@@ -488,6 +491,14 @@ install_fallback(Config) when is_list(Config) ->
mnesia_test_lib:kill_mnesia([Node1, Node2]),
timer:sleep(timer:seconds(1)), % Let it die!
+ ok = mnesia:start([{ignore_fallback_at_startup, true}]),
+ ok = mnesia:wait_for_tables([Tab, Tab2, Tab3], 10000),
+ ?match([{Tab, 6, test_nok}], mnesia:dirty_read({Tab, 6})),
+ mnesia_test_lib:kill_mnesia([Node1]),
+ application:set_env(mnesia, ignore_fallback_at_startup, false),
+
+ timer:sleep(timer:seconds(1)), % Let it die!
+
?match([], mnesia_test_lib:start_mnesia([Node1, Node2], [Tab, Tab2, Tab3])),
% Verify
@@ -510,6 +521,13 @@ install_fallback(Config) when is_list(Config) ->
file:delete(File3),
?match({error, _}, mnesia:install_fallback(File3)),
?match({error, _}, mnesia:install_fallback(File2, mnesia_badmod)),
+ ?match({error, _}, mnesia:install_fallback(File2, {foo, foo})),
+ ?match({error, _}, mnesia:install_fallback(File2, [{foo, foo}])),
+ ?match({error, {badarg, {skip_tables, _}}},
+ mnesia:install_fallback(File2, [{default_op, skip_tables},
+ {default_op, keep_tables},
+ {keep_tables, [Tab, Tab2, Tab3]},
+ {skip_tables, [foo,{asd}]}])),
?match(ok, mnesia:install_fallback(File2, mnesia_backup)),
?match(ok, file:delete(File)),
?match(ok, file:delete(File2)),
@@ -535,6 +553,7 @@ uninstall_fallback(Config) when is_list(Config) ->
?match(ok, mnesia:install_fallback(File2)),
?match(ok, file:delete(File)),
?match(ok, file:delete(File2)),
+ ?match({error, _}, mnesia:uninstall_fallback([foobar])),
?match(ok, mnesia:uninstall_fallback()),
mnesia_test_lib:kill_mnesia([Node1, Node2]),
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 2d1623b6ca..430c1f1d84 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -1338,11 +1338,11 @@ user_properties(Config) when is_list(Config) ->
?match([], mnesia:table_info(Tab2, user_properties)),
?match([], mnesia:table_info(Tab3, user_properties)),
- ?match({'EXIT', {no_exists, {Tab1, user_property, PropKey}}},
+ ?match({'EXIT', {aborted, {no_exists, {Tab1, user_property, PropKey}}}},
mnesia:read_table_property(Tab1, PropKey)),
- ?match({'EXIT', {no_exists, {Tab2, user_property, PropKey}}},
+ ?match({'EXIT', {aborted, {no_exists, {Tab2, user_property, PropKey}}}},
mnesia:read_table_property(Tab2, PropKey)),
- ?match({'EXIT', {no_exists, {Tab3, user_property, PropKey}}},
+ ?match({'EXIT', {aborted, {no_exists, {Tab3, user_property, PropKey}}}},
mnesia:read_table_property(Tab3, PropKey)),
?match({atomic, ok}, mnesia:write_table_property(Tab1, Prop)),
diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl
index 237984978e..f906670296 100644
--- a/lib/mnesia/test/mnesia_trans_access_test.erl
+++ b/lib/mnesia/test/mnesia_trans_access_test.erl
@@ -930,20 +930,20 @@ index_update_bag(Config)when is_list(Config) ->
[IPos] = mnesia_lib:val({Tab,index}),
ITab = mnesia_lib:val({index_test,{index, IPos}}),
io:format("~n Index ~p @ ~p => ~p ~n~n",[IPos,ITab, ets:tab2list(ITab)]),
- ?match([{2,1},{2,2},{12,1}], ets:tab2list(ITab)),
+ ?match([{2,1},{2,2},{12,1}], lists:keysort(1,ets:tab2list(ITab))),
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec5) end)),
{atomic, R60} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1,Rec5,Rec2], lists:sort(R60)),
- ?match([{2,1},{2,2},{12,1}], ets:tab2list(ITab)),
+ ?match([{2,1},{2,2},{12,1}], lists:keysort(1,ets:tab2list(ITab))),
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec3) end)),
{atomic, R61} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1,Rec5,Rec2], lists:sort(R61)),
{atomic, R62} = mnesia:transaction(fun() -> mnesia:index_read(Tab,12, ValPos) end),
?match([], lists:sort(R62)),
- ?match([{2,1},{2,2}], ets:tab2list(ITab)),
+ ?match([{2,1},{2,2}], lists:keysort(1,ets:tab2list(ITab))),
%% reset for rest of testcase
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec3) end)),
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index b23339e408..79dd495c4b 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.12.5
+MNESIA_VSN = 4.13