aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mnesia/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mnesia/src')
-rw-r--r--lib/mnesia/src/mnesia.erl146
-rw-r--r--lib/mnesia/src/mnesia.hrl6
-rw-r--r--lib/mnesia/src/mnesia_bup.erl10
-rw-r--r--lib/mnesia/src/mnesia_checkpoint.erl10
-rw-r--r--lib/mnesia/src/mnesia_controller.erl7
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl50
-rw-r--r--lib/mnesia/src/mnesia_frag.erl7
-rw-r--r--lib/mnesia/src/mnesia_index.erl46
-rw-r--r--lib/mnesia/src/mnesia_late_loader.erl2
-rw-r--r--lib/mnesia/src/mnesia_lib.erl20
-rw-r--r--lib/mnesia/src/mnesia_loader.erl13
-rw-r--r--lib/mnesia/src/mnesia_locker.erl9
-rw-r--r--lib/mnesia/src/mnesia_log.erl2
-rw-r--r--lib/mnesia/src/mnesia_recover.erl8
-rw-r--r--lib/mnesia/src/mnesia_schema.erl11
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl2
-rw-r--r--lib/mnesia/src/mnesia_text.erl2
-rw-r--r--lib/mnesia/src/mnesia_tm.erl31
18 files changed, 241 insertions, 141 deletions
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 1842769778..02bc884e36 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -160,7 +160,7 @@
{'sync_transaction', Retries::non_neg_integer()}.
-type table() :: atom().
-type storage_type() :: 'ram_copies' | 'disc_copies' | 'disc_only_copies'.
--type index_attr() :: atom() | non_neg_integer().
+-type index_attr() :: atom() | non_neg_integer() | {atom()}.
-type write_locks() :: 'write' | 'sticky_write'.
-type read_locks() :: 'read'.
-type lock_kind() :: write_locks() | read_locks().
@@ -168,6 +168,9 @@
-type snmp_struct() :: [{atom(), snmp_type() | tuple_of(snmp_type())}].
-type snmp_type() :: 'fix_string' | 'string' | 'integer'.
-type tuple_of(_T) :: tuple().
+-type config_key() :: extra_db_nodes | dc_dump_limit.
+-type config_value() :: [node()] | number().
+-type config_result() :: {ok, config_value()} | {error, term()}.
-define(DEFAULT_ACCESS, ?MODULE).
@@ -177,8 +180,8 @@
%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -278,7 +281,8 @@ stop() ->
Other -> Other
end.
--spec change_config(Config::atom(), Value::_) -> ok | {error, term()}.
+-spec change_config(Config::config_key(), Value::config_value()) ->
+ config_result().
change_config(extra_db_nodes, Ns) when is_list(Ns) ->
mnesia_controller:connect_nodes(Ns);
change_config(dc_dump_limit, N) when is_number(N), N > 0 ->
@@ -779,12 +783,16 @@ do_delete_object(Tid, Ts, Tab, Val, LockKind) ->
?ets_insert(Store, {Oid, Val, delete_object});
_ ->
case ?ets_match_object(Store, {Oid, '_', write}) of
- [] ->
- ?ets_match_delete(Store, {Oid, Val, '_'}),
- ?ets_insert(Store, {Oid, Val, delete_object});
- _ ->
- ?ets_delete(Store, Oid),
- ?ets_insert(Store, {Oid, Oid, delete})
+ [] ->
+ ?ets_match_delete(Store, {Oid, Val, '_'}),
+ ?ets_insert(Store, {Oid, Val, delete_object});
+ Ops ->
+ case lists:member({Oid, Val, write}, Ops) of
+ true ->
+ ?ets_delete(Store, Oid),
+ ?ets_insert(Store, {Oid, Oid, delete});
+ false -> ok
+ end
end
end,
ok;
@@ -830,18 +838,20 @@ read(Tid, Ts, Tab, Key, LockKind)
tid ->
Store = Ts#tidstore.store,
Oid = {Tab, Key},
- Objs =
- case LockKind of
- read ->
- mnesia_locker:rlock(Tid, Store, Oid);
- write ->
- mnesia_locker:rwlock(Tid, Store, Oid);
- sticky_write ->
- mnesia_locker:sticky_rwlock(Tid, Store, Oid);
- _ ->
- abort({bad_type, Tab, LockKind})
- end,
- add_written(?ets_lookup(Store, Oid), Tab, Objs);
+ ObjsFun =
+ fun() ->
+ case LockKind of
+ read ->
+ mnesia_locker:rlock(Tid, Store, Oid);
+ write ->
+ mnesia_locker:rwlock(Tid, Store, Oid);
+ sticky_write ->
+ mnesia_locker:sticky_rwlock(Tid, Store, Oid);
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end
+ end,
+ add_written(?ets_lookup(Store, Oid), Tab, ObjsFun, LockKind);
_Protocol ->
dirty_read(Tab, Key)
end;
@@ -1194,14 +1204,20 @@ add_previous(_Tid, Ts, _Type, Tab) ->
%% This routine fixes up the return value from read/1 so that
%% it is correct with respect to what this particular transaction
%% has already written, deleted .... etc
+%% The actual read from the table is not done if not needed due to local
+%% transaction context, and if so, no extra read lock is needed either.
-add_written([], _Tab, Objs) ->
- Objs; % standard normal fast case
-add_written(Written, Tab, Objs) ->
+add_written([], _Tab, ObjsFun, _LockKind) ->
+ ObjsFun(); % standard normal fast case
+add_written(Written, Tab, ObjsFun, LockKind) ->
case val({Tab, setorbag}) of
bag ->
- add_written_to_bag(Written, Objs, []);
+ add_written_to_bag(Written, ObjsFun(), []);
+ _ when LockKind == read;
+ LockKind == write ->
+ add_written_to_set(Written);
_ ->
+ _ = ObjsFun(), % Fall back to request new lock and read from source
add_written_to_set(Written)
end.
@@ -1261,6 +1277,14 @@ match_object(Tid, Ts, Tab, Pat, LockKind)
match_object(_Tid, _Ts, Tab, Pat, _LockKind) ->
abort({bad_type, Tab, Pat}).
+add_written_index(Store, Pos, Tab, Key, Objs) when is_integer(Pos) ->
+ Pat = setelement(Pos, val({Tab, wild_pattern}), Key),
+ add_written_match(Store, Pat, Tab, Objs);
+add_written_index(Store, Pos, Tab, Key, Objs) when is_tuple(Pos) ->
+ IxF = mnesia_index:index_vals_f(val({Tab, storage_type}), Tab, Pos),
+ Ops = find_ops(Store, Tab, '_'),
+ add_ix_match(Ops, Objs, IxF, Key, val({Tab, setorbag})).
+
add_written_match(S, Pat, Tab, Objs) ->
Ops = find_ops(S, Tab, Pat),
FixedRes = add_match(Ops, Objs, val({Tab, setorbag})),
@@ -1287,6 +1311,46 @@ add_match([{_Oid, Val, write}|R], Objs, bag) ->
add_match([{Oid, Val, write}|R], Objs, set) ->
add_match(R, [Val | deloid(Oid,Objs)],set).
+add_ix_match([], Objs, _IxF, _Key, _Type) ->
+ Objs;
+add_ix_match(Written, Objs, IxF, Key, ordered_set) ->
+ %% Must use keysort which is stable
+ add_ordered_match(lists:keysort(1, ix_filter_ops(IxF, Key, Written)), Objs, []);
+add_ix_match([{Oid, _, delete}|R], Objs, IxF, Key, Type) ->
+ add_ix_match(R, deloid(Oid, Objs), IxF, Key, Type);
+add_ix_match([{_Oid, Val, delete_object}|R], Objs, IxF, Key, Type) ->
+ case ix_match(Val, IxF, Key) of
+ true ->
+ add_ix_match(R, lists:delete(Val, Objs), IxF, Key, Type);
+ false ->
+ add_ix_match(R, Objs, IxF, Key, Type)
+ end;
+add_ix_match([{_Oid, Val, write}|R], Objs, IxF, Key, bag) ->
+ case ix_match(Val, IxF, Key) of
+ true ->
+ add_ix_match(R, [Val | lists:delete(Val, Objs)], IxF, Key, bag);
+ false ->
+ add_ix_match(R, Objs, IxF, Key, bag)
+ end;
+add_ix_match([{Oid, Val, write}|R], Objs, IxF, Key, set) ->
+ case ix_match(Val, IxF, Key) of
+ true ->
+ add_ix_match(R, [Val | deloid(Oid,Objs)],IxF,Key,set);
+ false ->
+ add_ix_match(R, Objs, IxF, Key, set)
+ end.
+
+ix_match(Val, IxF, Key) ->
+ lists:member(Key, IxF(Val)).
+
+ix_filter_ops(IxF, Key, Ops) ->
+ lists:filter(
+ fun({_Oid, Obj, write}) ->
+ ix_match(Obj, IxF, Key);
+ (_) ->
+ true
+ end, Ops).
+
%% For ordered_set only !!
add_ordered_match(Written = [{{_, Key}, _, _}|_], [Obj|Objs], Acc)
when Key > element(2, Obj) ->
@@ -1625,6 +1689,16 @@ index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind)
dirty_index_match_object(Tab, Pat, Attr); % Should be optimized?
tid ->
case mnesia_schema:attr_tab_to_pos(Tab, Attr) of
+ {_} ->
+ case LockKind of
+ read ->
+ Store = Ts#tidstore.store,
+ mnesia_locker:rlock_table(Tid, Store, Tab),
+ Objs = dirty_match_object(Tab, Pat),
+ add_written_match(Store, Pat, Tab, Objs);
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end;
Pos when Pos =< tuple_size(Pat) ->
case LockKind of
read ->
@@ -1672,8 +1746,8 @@ index_read(Tid, Ts, Tab, Key, Attr, LockKind)
false ->
Store = Ts#tidstore.store,
Objs = mnesia_index:read(Tid, Store, Tab, Key, Pos),
- Pat = setelement(Pos, val({Tab, wild_pattern}), Key),
- add_written_match(Store, Pat, Tab, Objs);
+ add_written_index(
+ Ts#tidstore.store, Pos, Tab, Key, Objs);
true ->
abort({bad_type, Tab, Attr, Key})
end;
@@ -1809,7 +1883,7 @@ remote_dirty_match_object(Tab, Pat) ->
false ->
mnesia_lib:db_match_object(Tab, Pat);
true ->
- PosList = val({Tab, index}),
+ PosList = regular_indexes(Tab),
remote_dirty_match_object(Tab, Pat, PosList)
end.
@@ -1841,7 +1915,7 @@ remote_dirty_select(Tab, Spec) ->
false ->
mnesia_lib:db_select(Tab, Spec);
true ->
- PosList = val({Tab, index}),
+ PosList = regular_indexes(Tab),
remote_dirty_select(Tab, Spec, PosList)
end;
_ ->
@@ -1908,6 +1982,8 @@ dirty_index_match_object(Pat, _Attr) ->
dirty_index_match_object(Tab, Pat, Attr)
when is_atom(Tab), Tab /= schema, is_tuple(Pat), tuple_size(Pat) > 2 ->
case mnesia_schema:attr_tab_to_pos(Tab, Attr) of
+ {_} ->
+ dirty_match_object(Tab, Pat);
Pos when Pos =< tuple_size(Pat) ->
case has_var(element(2, Pat)) of
false ->
@@ -2682,7 +2758,7 @@ del_table_index(Tab, Ix) ->
-spec transform_table(Tab::table(), Fun, [Attr]) -> t_result(ok) when
Attr :: atom(),
- Fun:: fun((Record::tuple()) -> Transformed::tuple()).
+ Fun:: fun((Record::tuple()) -> Transformed::tuple()) | ignore.
transform_table(Tab, Fun, NewA) ->
try val({Tab, record_name}) of
OldRN -> mnesia_schema:transform_table(Tab, Fun, NewA, OldRN)
@@ -2693,7 +2769,7 @@ transform_table(Tab, Fun, NewA) ->
-spec transform_table(Tab::table(), Fun, [Attr], RecName) -> t_result(ok) when
RecName :: atom(),
Attr :: atom(),
- Fun:: fun((Record::tuple()) -> Transformed::tuple()).
+ Fun:: fun((Record::tuple()) -> Transformed::tuple()) | ignore.
transform_table(Tab, Fun, NewA, NewRN) ->
mnesia_schema:transform_table(Tab, Fun, NewA, NewRN).
@@ -3238,3 +3314,7 @@ put_activity_id(Activity) ->
mnesia_tm:put_activity_id(Activity).
put_activity_id(Activity,Fun) ->
mnesia_tm:put_activity_id(Activity,Fun).
+
+regular_indexes(Tab) ->
+ PosList = val({Tab, index}),
+ [P || P <- PosList, is_integer(P)].
diff --git a/lib/mnesia/src/mnesia.hrl b/lib/mnesia/src/mnesia.hrl
index da7e662288..fe48a6fe3d 100644
--- a/lib/mnesia/src/mnesia.hrl
+++ b/lib/mnesia/src/mnesia.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,6 +47,10 @@
-define(catch_val(Var), (try ?ets_lookup_element(mnesia_gvar, Var, 2)
catch error:_ -> {'EXIT', {badarg, []}} end)).
+-define(catch_val_and_stack(Var),
+ (try ?ets_lookup_element(mnesia_gvar, Var, 2)
+ catch error:_:_Stacktrace -> {'EXIT', _Stacktrace} end)).
+
%% It's important that counter is first, since we compare tid's
-record(tid,
diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl
index 34f16f178b..e57fc5199d 100644
--- a/lib/mnesia/src/mnesia_bup.erl
+++ b/lib/mnesia/src/mnesia_bup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -90,9 +90,9 @@ iterate(Mod, Fun, Opaque, Acc) ->
catch throw:Err ->
close_read(R2),
Err;
- _:Reason ->
+ _:Reason:Stacktrace ->
close_read(R2),
- {error, {Reason, erlang:get_stacktrace()}}
+ {error, {Reason, Stacktrace}}
end
catch throw:{error,_} = Err ->
Err
@@ -198,9 +198,9 @@ do_read_schema_section(R) ->
try
{R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]),
do_read_schema_section(R3, verify_header(RawSchema), [])
- catch T:E ->
+ catch T:E:S ->
close_read(R2),
- erlang:raise(T,E,erlang:get_stacktrace())
+ erlang:raise(T,E,S)
end.
do_read_schema_section(R, {ok, B, C, []}, Acc) ->
diff --git a/lib/mnesia/src/mnesia_checkpoint.erl b/lib/mnesia/src/mnesia_checkpoint.erl
index 8112378ffd..3273d3d27e 100644
--- a/lib/mnesia/src/mnesia_checkpoint.erl
+++ b/lib/mnesia/src/mnesia_checkpoint.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017
+%% Copyright Ericsson AB 1996-2018
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1269,9 +1269,9 @@ system_code_change(Cp, _Module, _OldVsn, _Extra) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
- _VaLuE_ -> _VaLuE_
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
+ Value -> Value
end.
-
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 11185a1762..882de0d613 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -185,9 +185,10 @@ max_loaders() ->
worker_res
}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index f0ed7aef4a..8ab11be2d3 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -67,10 +67,10 @@ get_log_writes() ->
incr_log_writes() ->
Left = mnesia_lib:incr_counter(trans_log_writes_left, -1),
if
- Left > 0 ->
- ignore;
+ Left =:= 0 ->
+ adjust_log_writes(true);
true ->
- adjust_log_writes(true)
+ ignore
end.
adjust_log_writes(DoCast) ->
@@ -191,8 +191,7 @@ do_perform_dump(Cont, InPlace, InitBy, Regulator, OldVersion) ->
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(),
+ catch _:R:ST when R =/= fatal ->
Reason = {"Transaction log dump error: ~tp~n", [{R, ST}]},
close_files(InPlace, {error, Reason}, InitBy),
exit(Reason)
@@ -273,17 +272,12 @@ do_insert_rec(Tid, Rec, InPlace, InitBy, LogV) ->
end
end,
D = Rec#commit.disc_copies,
- ExtOps = commit_ext(Rec),
insert_ops(Tid, disc_copies, D, InPlace, InitBy, LogV),
- [insert_ops(Tid, Ext, Ops, InPlace, InitBy, LogV) ||
- {Ext, Ops} <- ExtOps,
- storage_semantics(Ext) == disc_copies],
+ insert_ext_ops(Tid, commit_ext(Rec), InPlace, InitBy),
case InitBy of
startup ->
DO = Rec#commit.disc_only_copies,
- insert_ops(Tid, disc_only_copies, DO, InPlace, InitBy, LogV),
- [insert_ops(Tid, Ext, Ops, InPlace, InitBy, LogV) ||
- {Ext, Ops} <- ExtOps, storage_semantics(Ext) == disc_only_copies];
+ insert_ops(Tid, disc_only_copies, DO, InPlace, InitBy, LogV);
_ ->
ignore
end.
@@ -291,11 +285,8 @@ do_insert_rec(Tid, Rec, InPlace, InitBy, LogV) ->
commit_ext(#commit{ext = []}) -> [];
commit_ext(#commit{ext = Ext}) ->
case lists:keyfind(ext_copies, 1, Ext) of
- {_, C} ->
- lists:foldl(fun({Ext0, Op}, D) ->
- orddict:append(Ext0, Op, D)
- end, orddict:new(), C);
- false -> []
+ {_, C} -> C;
+ false -> []
end.
update(_Tid, [], _DumperMode) ->
@@ -325,13 +316,27 @@ perform_update(Tid, SchemaOps, _DumperMode, _UseDir) ->
?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
close_files(InPlace, ok, InitBy),
ok
- catch _:Reason when Reason =/= fatal ->
- ST = erlang:get_stacktrace(),
+ catch _:Reason:ST when Reason =/= fatal ->
Error = {error, {"Schema update error", {Reason, ST}}},
close_files(InPlace, Error, InitBy),
fatal("Schema update error ~tp ~tp", [{Reason,ST}, SchemaOps])
end.
+insert_ext_ops(Tid, ExtOps, InPlace, InitBy) ->
+ %% Note: ext ops cannot be part of pre-4.3 logs, so there's no need
+ %% to support the old operation order, as in `insert_ops'
+ lists:foreach(
+ fun ({Ext, Op}) ->
+ case storage_semantics(Ext) of
+ Semantics when Semantics == disc_copies;
+ Semantics == disc_only_copies, InitBy == startup ->
+ insert_op(Tid, Ext, Op, InPlace, InitBy);
+ _Other ->
+ ok
+ end
+ end,
+ ExtOps).
+
insert_ops(_Tid, _Storage, [], _InPlace, _InitBy, _) -> ok;
insert_ops(Tid, Storage, [Op], InPlace, InitBy, Ver) when Ver >= "4.3"->
insert_op(Tid, Storage, Op, InPlace, InitBy),
@@ -1471,8 +1476,9 @@ regulate(RegulatorPid) ->
{regulated, RegulatorPid} -> ok
end.
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl
index c39f30e140..8f7dd321b0 100644
--- a/lib/mnesia/src/mnesia_frag.erl
+++ b/lib/mnesia/src/mnesia_frag.erl
@@ -1,7 +1,7 @@
%%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1157,9 +1157,10 @@ remove_node(Node, Cs) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helpers
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index f8b3b9cd02..6f1c21e3b9 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
@@ -14,7 +14,7 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -37,7 +37,7 @@
db_match_erase/2,
get_index_table/2,
get_index_table/3,
-
+
tab2filename/2,
init_index/2,
init_indecies/3,
@@ -45,6 +45,7 @@
del_transient/3,
del_index_table/3,
+ index_vals_f/3,
index_info/2,
ext_index_instances/1]).
@@ -60,9 +61,14 @@ read(Tid, Store, Tab, IxKey, Pos) ->
ResList = mnesia_locker:ixrlock(Tid, Store, Tab, IxKey, Pos),
%% Remove all tuples which don't include Ixkey, happens when Tab is a bag
case val({Tab, setorbag}) of
- bag ->
+ bag when is_integer(Pos) ->
mnesia_lib:key_search_all(IxKey, Pos, ResList);
- _ ->
+ bag when is_tuple(Pos) ->
+ TabStorage = val({Tab, storage_type}),
+ ValsF = index_vals_f(TabStorage, Tab, Pos),
+ [Obj || Obj <- ResList,
+ lists:member(IxKey, ValsF(Obj))];
+ _ ->
ResList
end.
@@ -136,7 +142,7 @@ del_object_index2([], _, _Storage, _Tab, _K, _Obj) -> ok;
del_object_index2([{{Pos, Type}, Ixt} | Tail], SoB, Storage, Tab, K, Obj) ->
ValsF = index_vals_f(Storage, Tab, Pos),
case SoB of
- bag ->
+ bag ->
del_object_bag(Type, ValsF, Tab, K, Obj, Ixt);
_ -> %% If set remove the tuple in index table
del_ixes(Type, Ixt, ValsF, Obj, K)
@@ -197,7 +203,7 @@ merge([], _, _, Ack) ->
realkeys(Tab, Pos, IxKey) ->
Index = get_index_table(Tab, Pos),
db_get(Index, IxKey). % a list on the form [{IxKey, RealKey1} , ....
-
+
dirty_select(Tab, Spec, Pos) when is_integer(Pos) ->
%% Assume that we are on the node where the replica is
%% Returns the records without applying the match spec
@@ -233,7 +239,7 @@ dirty_read2(Tab, IxKey, Pos) ->
end, Acc, mnesia_lib:db_get(Storage, Tab, K))
end, [], Keys)).
-pick_index([{{{Pfx,_},IxType}, Ixt}|_], _Tab, {_} = Pfx) ->
+pick_index([{{{Pfx,_,_},IxType}, Ixt}|_], _Tab, {_} = Pfx) ->
{IxType, Ixt};
pick_index([{{Pos,IxType}, Ixt}|_], _Tab, Pos) ->
{IxType, Ixt};
@@ -242,7 +248,7 @@ pick_index([_|T], Tab, Pos) ->
pick_index([], Tab, Pos) ->
mnesia:abort({no_exist, Tab, {index, Pos}}).
-
+
%%%%%%% Creation, Init and deletion routines for index tables
%% We can have several indexes on the same table
@@ -387,12 +393,12 @@ init_ext_index(Tab, Storage, Alias, Mod, [{Pos,Type} | Tail]) ->
create_fun(Cont, Tab, Pos) ->
IxF = index_vals_f(disc_only_copies, Tab, Pos),
fun(read) ->
- Data =
+ Data =
case Cont of
{start, KeysPerChunk} ->
mnesia_lib:db_init_chunk(
disc_only_copies, Tab, KeysPerChunk);
- '$end_of_table' ->
+ '$end_of_table' ->
'$end_of_table';
_Else ->
mnesia_lib:db_chunk(disc_only_copies, Cont)
@@ -462,7 +468,7 @@ add_index_info(Tab, SetOrBag, IxElem) ->
%% Check later if mnesia_tm is sensitive about the order
mnesia_lib:set({Tab, index_info}, IndexInfo),
mnesia_lib:set({Tab, index}, index_positions(IndexInfo)),
- mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:set({Tab, commit_work},
mnesia_lib:sort_commit([IndexInfo | Commit]));
{value, Old} ->
%% We could check for consistency here
@@ -470,7 +476,7 @@ add_index_info(Tab, SetOrBag, IxElem) ->
mnesia_lib:set({Tab, index_info}, Index),
mnesia_lib:set({Tab, index}, index_positions(Index)),
NewC = lists:keyreplace(index, 1, Commit, Index),
- mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:set({Tab, commit_work},
mnesia_lib:sort_commit(NewC))
end.
@@ -488,19 +494,19 @@ del_index_info(Tab, Pos) ->
element(1,P)=/=Pos
end,
Old#index.pos_list) of
- [] ->
+ [] ->
IndexInfo = index_info(Old#index.setorbag,[]),
mnesia_lib:set({Tab, index_info}, IndexInfo),
mnesia_lib:set({Tab, index}, index_positions(IndexInfo)),
NewC = lists:keydelete(index, 1, Commit),
- mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:set({Tab, commit_work},
mnesia_lib:sort_commit(NewC));
New ->
Index = Old#index{pos_list = New},
mnesia_lib:set({Tab, index_info}, Index),
mnesia_lib:set({Tab, index}, index_positions(Index)),
NewC = lists:keyreplace(index, 1, Commit, Index),
- mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:set({Tab, commit_work},
mnesia_lib:sort_commit(NewC))
end
end.
@@ -537,7 +543,7 @@ db_match_erase({{ext,_,_} = Ext, Ixt}, Pat) ->
mnesia_lib:db_match_erase(Ext, Ixt, Pat);
db_match_erase({dets, Ixt}, Pat) ->
ok = dets:match_delete(Ixt, Pat).
-
+
db_select({ram, Ixt}, Pat) ->
ets:select(Ixt, Pat);
db_select({{ext,_,_} = Ext, Ixt}, Pat) ->
@@ -545,7 +551,7 @@ db_select({{ext,_,_} = Ext, Ixt}, Pat) ->
db_select({dets, Ixt}, Pat) ->
dets:select(Ixt, Pat).
-
+
get_index_table(Tab, Pos) ->
get_index_table(Tab, val({Tab, storage_type}), Pos).
diff --git a/lib/mnesia/src/mnesia_late_loader.erl b/lib/mnesia/src/mnesia_late_loader.erl
index e4f8dcf2b9..45afda6e4b 100644
--- a/lib/mnesia/src/mnesia_late_loader.erl
+++ b/lib/mnesia/src/mnesia_late_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index 53fdd76de8..6abc05fade 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -116,7 +116,7 @@
lock_table/1,
mkcore/1,
not_active_here/1,
- other_val/1,
+ other_val/2,
overload_read/0,
overload_read/1,
overload_set/2,
@@ -435,8 +435,8 @@ validate_record(Tab, Obj) ->
%%
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> other_val(Var, Stacktrace);
_VaLuE_ -> _VaLuE_
end.
@@ -446,9 +446,9 @@ set(Var, Val) ->
unset(Var) ->
?ets_delete(mnesia_gvar, Var).
-other_val(Var) ->
+other_val(Var, Stacktrace) ->
case other_val_1(Var) of
- error -> pr_other(Var);
+ error -> pr_other(Var, Stacktrace);
Val -> Val
end.
@@ -460,8 +460,8 @@ other_val_1(Var) ->
_ -> error
end.
--spec pr_other(_) -> no_return().
-pr_other(Var) ->
+-spec pr_other(_, _) -> no_return().
+pr_other(Var, Stacktrace) ->
Why =
case is_running() of
no -> {node_not_running, node()};
@@ -469,7 +469,7 @@ pr_other(Var) ->
end,
verbose("~p (~tp) val(mnesia_gvar, ~tw) -> ~p ~tp ~n",
[self(), process_info(self(), registered_name),
- Var, Why, erlang:get_stacktrace()]),
+ Var, Why, Stacktrace]),
mnesia:abort(Why).
%% Some functions for list valued variables
@@ -929,7 +929,7 @@ error_desc(no_transaction) -> "Operation not allowed outside transactions";
error_desc(combine_error) -> "Table options were ilegally combined";
error_desc(bad_index) -> "Index already exists or was out of bounds";
error_desc(already_exists) -> "Some schema option we try to set is already on";
-error_desc(index_exists)-> "Some ops can not be performed on tabs with index";
+error_desc(index_exists)-> "Some ops cannot be performed on tabs with index";
error_desc(no_exists)-> "Tried to perform op on non-existing (non alive) item";
error_desc(system_limit) -> "Some system_limit was exhausted";
error_desc(mnesia_down) -> "A transaction involving objects at some remote "
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index 39704c65f9..2cdae0c906 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,9 +34,10 @@
-include("mnesia.hrl").
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -535,7 +536,7 @@ init_table(Tab, _, Fun, _DetsInfo,_) ->
try
true = ets:init_table(Tab, Fun),
ok
- catch _:Else -> {Else, erlang:get_stacktrace()}
+ catch _:Else:Stacktrace -> {Else, Stacktrace}
end.
@@ -777,9 +778,9 @@ do_send_table(Pid, Tab, Storage, RemoteS) ->
throw:receiver_died ->
cleanup_tab_copier(Pid, Storage, Tab),
ok;
- error:Reason -> %% Prepare failed
+ error:Reason:Stacktrace -> %% Prepare failed
cleanup_tab_copier(Pid, Storage, Tab),
- {error, {tab_copier, Tab, {Reason, erlang:get_stacktrace()}}}
+ {error, {tab_copier, Tab, {Reason, Stacktrace}}}
after
unlink(whereis(mnesia_tm))
end.
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index 073b48abc0..f68626413e 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -97,10 +97,11 @@ init(Parent) ->
end,
loop(#state{supervisor = Parent}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
- _VaLuE_ -> _VaLuE_
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
+ Value -> Value
end.
reply(From, R) ->
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index a2de23a2a3..03411ace41 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index d792070332..2ccea1ea6d 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -177,10 +177,10 @@ disconnect(Node) ->
log_decision(D) ->
cast({log_decision, D}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _Reason} ->
- mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index 71952af31c..ef38adca1e 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -181,9 +181,10 @@ exit_on_error({error, Reason}) ->
exit_on_error(GoodRes) ->
GoodRes.
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -2695,10 +2696,10 @@ prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
Objs ->
mnesia_lib:db_fixtable(Storage, Tab, false),
{true, Objs, mandatory}
- catch _:Reason ->
+ catch _:Reason:Stacktrace ->
mnesia_lib:db_fixtable(Storage, Tab, false),
mnesia_lib:important("Transform function failed: '~tp' in '~tp'",
- [Reason, erlang:get_stacktrace()]),
+ [Reason, Stacktrace]),
exit({"Bad transform function", Tab, Fun, node(), Reason})
end
end;
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index dfaa20d2d3..21a308cfb6 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/mnesia/src/mnesia_text.erl b/lib/mnesia/src/mnesia_text.erl
index 7d24d09472..cc21621ff4 100644
--- a/lib/mnesia/src/mnesia_text.erl
+++ b/lib/mnesia/src/mnesia_text.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index ebf580d09e..8b79fca1d7 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -121,10 +121,11 @@ init(Parent) ->
proc_lib:init_ack(Parent, {ok, self()}),
doit_loop(#state{supervisor = Parent}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
- _VaLuE_ -> _VaLuE_
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
+ Value -> Value
end.
reply({From,Ref}, R) ->
@@ -597,9 +598,9 @@ recover_coordinator(Tid, Etabs) ->
false -> %% When killed before store havn't been copied to
ok %% to the new nested trans store.
end
- catch _:Reason ->
+ catch _:Reason:Stacktrace ->
dbg_out("Recovery of coordinator ~p failed: ~tp~n",
- [Tid, {Reason, erlang:get_stacktrace()}]),
+ [Tid, {Reason, Stacktrace}]),
Protocol = asym_trans,
tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes)
end,
@@ -742,8 +743,9 @@ non_transaction(OldState, Fun, Args, ActivityKind, Mod) ->
{aborted, Reason} -> mnesia:abort(Reason);
Res -> Res
catch
- throw:Throw -> throw(Throw);
- _:Reason -> exit(Reason)
+ throw:Throw -> throw(Throw);
+ error:Reason:ST -> exit({Reason, ST});
+ exit:Reason -> exit(Reason)
after
case OldState of
undefined -> erase(mnesia_activity_state);
@@ -825,8 +827,7 @@ execute_transaction(Fun, Args, Factor, Retries, Type) ->
catch throw:Value -> %% User called throw
Reason = {aborted, {throw, Value}},
return_abort(Fun, Args, Reason);
- error:Reason ->
- ST = erlang:get_stacktrace(),
+ error:Reason:ST ->
check_exit(Fun, Args, Factor, Retries, {Reason,ST}, Type);
_:Reason ->
check_exit(Fun, Args, Factor, Retries, Reason, Type)
@@ -1661,7 +1662,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?eval_debug_fun({?MODULE, commit_participant, pre}, [{tid, Tid}]),
try mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
{Modified, C = #commit{}, DumperMode} ->
- %% If we can not find any local unclear decision
+ %% If we cannot find any local unclear decision
%% we should presume abort at startup recovery
case lists:member(node(), DiscNs) of
false ->
@@ -1796,14 +1797,13 @@ do_update(Tid, Storage, [Op | Ops], OldRes) ->
try do_update_op(Tid, Storage, Op) of
ok -> do_update(Tid, Storage, Ops, OldRes);
NewRes -> do_update(Tid, Storage, Ops, NewRes)
- catch _:Reason ->
+ catch _:Reason:ST ->
%% 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: ~tp -> {'EXIT', ~tp}~n",
[Tid, Op, {Reason, ST}]),
do_update(Tid, Storage, Ops, OldRes)
@@ -1914,11 +1914,10 @@ commit_clear([H|R], Tid, Storage, Tab, K, Obj)
do_snmp(_, []) -> ok;
do_snmp(Tid, [Head|Tail]) ->
try mnesia_snmp_hook:update(Head)
- catch _:Reason ->
+ catch _:Reason:ST ->
%% 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: ~tp -> {'EXIT', ~tp}~n",
[Tid, Head, {Reason, ST}])
end,
@@ -2212,7 +2211,7 @@ display_pid_info(Pid) ->
Other
end,
Reds = fetch(reductions, Info),
- LM = length(fetch(messages, Info)),
+ LM = fetch(message_queue_len, Info),
pformat(io_lib:format("~p", [Pid]),
io_lib:format("~tp", [Call]),
io_lib:format("~tp", [Curr]), Reds, LM)