diff options
author | Dan Gudmundsson <[email protected]> | 2011-12-09 13:28:19 +0100 |
---|---|---|
committer | Dan Gudmundsson <[email protected]> | 2011-12-09 13:28:19 +0100 |
commit | e3bcbd4451cdb1dd0a826810a898c2d0e9fa390d (patch) | |
tree | c7adb5a7b5e3df5b332407a779971c8a6a1d451f /lib/mnesia/test | |
parent | 78bbed8a811116bb9a3332336e97fecd06a338db (diff) | |
parent | fe9e57f765c428e7e9b94e24250d83474e77f09f (diff) | |
download | otp-e3bcbd4451cdb1dd0a826810a898c2d0e9fa390d.tar.gz otp-e3bcbd4451cdb1dd0a826810a898c2d0e9fa390d.tar.bz2 otp-e3bcbd4451cdb1dd0a826810a898c2d0e9fa390d.zip |
Merge branch 'dgud/mnesia/read-sticky-bug/OTP-9786'
* dgud/mnesia/read-sticky-bug/OTP-9786:
[mnesia] Read record from correct node
[mnesia] Fixed sticky read lock bug
[mnesia] Whitespace fixes
Conflicts:
lib/mnesia/src/mnesia_log.erl
Diffstat (limited to 'lib/mnesia/test')
-rw-r--r-- | lib/mnesia/test/mnesia_atomicity_test.erl | 96 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_test_lib.erl | 104 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_test_lib.hrl | 14 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_trans_access_test.erl | 839 |
4 files changed, 530 insertions, 523 deletions
diff --git a/lib/mnesia/test/mnesia_atomicity_test.erl b/lib/mnesia/test/mnesia_atomicity_test.erl index cf878fc820..06c4d16d71 100644 --- a/lib/mnesia/test/mnesia_atomicity_test.erl +++ b/lib/mnesia/test/mnesia_atomicity_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -31,13 +31,13 @@ end_per_testcase(Func, Conf) -> mnesia_test_lib:end_per_testcase(Func, Conf). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -all() -> +all() -> [explicit_abort_in_middle_of_trans, runtime_error_in_middle_of_trans, kill_self_in_middle_of_trans, throw_in_middle_of_trans, {group, mnesia_down_in_middle_of_trans}]. -groups() -> +groups() -> [{mnesia_down_in_middle_of_trans, [], [mnesia_down_during_infinite_trans, {group, lock_waiter}, {group, restart_check}]}, @@ -297,7 +297,7 @@ mnesia_down_during_infinite_trans(Config) when is_list(Config) -> ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write({Tab, 1, test_ok}) end)), mnesia_test_lib:start_sync_transactions([A2, A1]), - + %% Obtain a write lock and wait forever RecA = {Tab, 1, test_not_ok}, A1 ! fun() -> mnesia:write(RecA) end, @@ -471,12 +471,12 @@ lock_waiter_w_wt(Config) when is_list(Config) -> start_lock_waiter(BlockOpA, BlockOpB, Config) -> [N1, N2] = Nodes = ?acquire_nodes(2, Config), - + TabName = mk_tab_name(lock_waiter_), ?match({atomic, ok}, mnesia:create_table(TabName, [{ram_copies, [N1, N2]}])), - - %% initialize the table with object {1, c} - when there + + %% initialize the table with object {1, c} - when there %% is a read transaction, the read will find that value ?match({atomic, ok}, mnesia:sync_transaction(fun() -> mnesia:write({TabName, 1, c}) end)), rpc:call(N2, ?MODULE, sync_tid_release, []), @@ -484,7 +484,7 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) -> Tester = self(), Fun_A =fun() -> NewCounter = incr_restart_counter(), - if + if NewCounter == 1 -> Tester ! go_ahead_test, receive go_ahead -> ok end; @@ -493,13 +493,13 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) -> lock_waiter_fun(BlockOpA, TabName, a), NewCounter end, - + %% it's not possible to just spawn the transaction, because %% the result shall be evaluated A = spawn_link(N1, ?MODULE, perform_restarted_transaction, [Fun_A]), - + ?match(ok, receive go_ahead_test -> ok after 10000 -> timeout end), - + mnesia_test_lib:sync_trans_tid_serial([N1, N2]), Fun_B = fun() -> @@ -507,21 +507,21 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) -> A ! go_ahead, wait(infinity) end, - + B = spawn_link(N2, mnesia, transaction, [Fun_B, 100]), - + io:format("waiting for A (~p on ~p) to be in the queue ~n", [A, [N1, N2]]), wait_for_a(A, [N1, N2]), - - io:format("Queus ~p~n", + + io:format("Queus ~p~n", [[{N,rpc:call(N, mnesia, system_info, [lock_queue])} || N <- Nodes]]), - + KillNode = node(B), io:format("A was in the queue, time to kill Mnesia on B's node (~p on ~p)~n", [B, KillNode]), - + mnesia_test_lib:kill_mnesia([KillNode]), % kill mnesia of fun B - + %% Read Ops does not need to be restarted ExpectedCounter = if @@ -535,20 +535,22 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) -> BlockOpA == rt, BlockOpB /= sw -> 1; true -> 2 end, - ?match_multi_receive([{'EXIT', A, {atomic, ExpectedCounter}}, - {'EXIT', B, killed}]), - + receive {'EXIT', B, _} -> ok + after 3000 -> ?error("Timeout~n", []) end, + receive {'EXIT', A, Exp1} -> ?match({atomic, ExpectedCounter}, Exp1) + after 3000 -> ?error("Timeout~n", []) end, + %% the expected result depends on the transaction of %% fun A - when that doesn't change the object in the %% table (e.g. it is a read) then the predefined %% value {Tabname, 1, c} is expected to be the result here - ExpectedResult = + ExpectedResult = case BlockOpA of w -> {TabName, 1, a}; sw ->{TabName, 1, a}; _all_other -> {TabName, 1, c} end, - + ?match({atomic, [ExpectedResult]}, mnesia:transaction(fun() -> mnesia:read({TabName, 1}) end, 100)), ?verify_mnesia([N1], [N2]). @@ -567,7 +569,7 @@ lock_waiter_fun(Op, TabName, Val) -> srw -> mnesia:read(TabName, 1, sticky_write); sw -> mnesia:s_write({TabName, 1, Val}) end. - + wait_for_a(Pid, Nodes) -> wait_for_a(Pid, Nodes, 5). @@ -589,12 +591,12 @@ check_q(Pid, [_ | Tail], N, Count) -> check_q(Pid, [], N, Count) -> timer:sleep(500), wait_for_a(Pid, N, Count - 1). - + perform_restarted_transaction (Fun_Trans) -> %% the result of the transaction shall be: %% - undefined (if the transaction was never executed) %% - Times ( number of times that the transaction has been executed) - + Result = mnesia:transaction(Fun_Trans, 100), exit(Result). @@ -666,10 +668,10 @@ restart_sw_two(Config) when is_list(Config) -> start_restart_check(RestartOp, ReplicaNeed, Config) -> [N1, N2, N3] = Nodes = ?acquire_nodes(3, Config), - + {TabName, _TabNodes} = create_restart_table(ReplicaNeed, Nodes), - - %% initialize the table with object {1, c} - when there + + %% initialize the table with object {1, c} - when there %% is a read transaction, the read will find that value ?match({atomic, ok}, mnesia:sync_transaction(fun() -> mnesia:write({TabName, 1, c}) end)), @@ -681,9 +683,9 @@ start_restart_check(RestartOp, ReplicaNeed, Config) -> NewCounter = incr_restart_counter(), case NewCounter of 1 -> - mnesia:write({TabName, 1, d}), + mnesia:write({TabName, 1, d}), %% send a message to the test proc - Coord ! {self(),fun_a_is_blocked}, + Coord ! {self(),fun_a_is_blocked}, receive go_ahead -> ok end; _ -> %% the fun will NOT be blocked here @@ -691,19 +693,19 @@ start_restart_check(RestartOp, ReplicaNeed, Config) -> end, NewCounter end, - + A = spawn_link(N1, ?MODULE, perform_restarted_transaction, [Fun_A]), - ?match_receive({A,fun_a_is_blocked}), - + ?match_receive({A,fun_a_is_blocked}), + %% mnesia shall be killed at that node, where A is reading %% the information from kill_where_to_read(TabName, N1, [N2, N3]), - + %% wait some time to let mnesia go down and spread those news around %% fun A shall be able to finish its job before being restarted - wait(500), + wait(500), A ! go_ahead, - + %% the sticky write doesnt work on remote nodes !!! ExpectedMsg = case RestartOp of @@ -717,19 +719,19 @@ start_restart_check(RestartOp, ReplicaNeed, Config) -> {'EXIT',A,{atomic, 2}} end end, - - ?match_receive(ExpectedMsg), - + + ?match_receive(ExpectedMsg), + %% now mnesia has to be started again on the node KillNode %% because the next test suite will need it ?match([], mnesia_test_lib:start_mnesia(Nodes, [TabName])), - - + + %% the expected result depends on the transaction of %% fun A - when that doesnt change the object in the %% table (e.g. it is a read) then the predefined %% value {Tabname, 1, c} is expected to be the result here - + ExpectedResult = case ReplicaNeed of one -> @@ -746,7 +748,7 @@ start_restart_check(RestartOp, ReplicaNeed, Config) -> ?verify_mnesia(Nodes, []). create_restart_table(ReplicaNeed, [_N1, N2, N3]) -> - TabNodes = + TabNodes = case ReplicaNeed of one -> [N2]; two -> [N2, N3] @@ -754,7 +756,7 @@ create_restart_table(ReplicaNeed, [_N1, N2, N3]) -> TabName = mk_tab_name(restart_check_), ?match({atomic, ok}, mnesia:create_table(TabName, [{ram_copies, TabNodes}])), {TabName, TabNodes}. - + restart_fun_A(Op, TabName) -> case Op of rt -> mnesia:read_lock_table(TabName); @@ -774,8 +776,8 @@ kill_where_to_read(TabName, N1, Nodes) -> ?error("Fault while killing Mnesia: ~p~n", [Read]), mnesia_test_lib:kill_mnesia(Nodes) end. - -sync_tid_release() -> + +sync_tid_release() -> sys:get_status(whereis(mnesia_tm)), sys:get_status(whereis(mnesia_locker)), ok. diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl index 9da45975d5..ba5bf84e24 100644 --- a/lib/mnesia/test/mnesia_test_lib.erl +++ b/lib/mnesia/test/mnesia_test_lib.erl @@ -99,7 +99,7 @@ slave_start_link/0, slave_start_link/1, slave_sup/0, - + start_mnesia/1, start_mnesia/2, start_appls/2, @@ -131,7 +131,7 @@ struct/1, init_per_testcase/2, end_per_testcase/2, - kill_tc/2 + kill_tc/2 ]). -include("mnesia_test_lib.hrl"). @@ -187,7 +187,7 @@ verbose(Format, Args, File, Line) -> ok end end. - + -record('REASON', {file, line, desc}). error(Format, Args, File, Line) -> @@ -196,9 +196,9 @@ error(Format, Args, File, Line) -> line = Line, desc = Args}, case global:whereis_name(mnesia_test_case_sup) of - undefined -> + undefined -> ignore; - Pid -> + Pid -> Pid ! Fail %% global:send(mnesia_test_case_sup, Fail), end, @@ -217,7 +217,7 @@ storage_type(Default, Config) -> default_config() -> [{nodes, default_nodes()}]. -default_nodes() -> +default_nodes() -> mk_nodes(3, []). mk_nodes(0, Nodes) -> @@ -231,7 +231,7 @@ mk_nodes(N, Nodes) when N > 0 -> mk_node(N, Name, Host) -> list_to_atom(lists:concat([Name ++ integer_to_list(N) ++ "@" ++ Host])). - + slave_start_link() -> slave_start_link(node()). @@ -247,11 +247,11 @@ slave_start_link(Host, Name) -> slave_start_link(Host, Name, Retries) -> Debug = atom_to_list(mnesia:system_info(debug)), - Args = "-mnesia debug " ++ Debug ++ + Args = "-mnesia debug " ++ Debug ++ + " -pa " ++ + filename:dirname(code:which(?MODULE)) ++ " -pa " ++ - filename:dirname(code:which(?MODULE)) ++ - " -pa " ++ - filename:dirname(code:which(mnesia)), + filename:dirname(code:which(mnesia)), case starter(Host, Name, Args) of {ok, NewNode} -> ?match(pong, net_adm:ping(NewNode)), @@ -264,8 +264,8 @@ slave_start_link(Host, Name, Retries) -> {ok, NewNode}; {error, Reason} when Retries == 0-> {error, Reason}; - {error, Reason} -> - io:format("Could not start slavenode ~p ~p retrying~n", + {error, Reason} -> + io:format("Could not start slavenode ~p ~p retrying~n", [{Host, Name, Args}, Reason]), timer:sleep(500), slave_start_link(Host, Name, Retries - 1) @@ -284,7 +284,7 @@ starter(Host, Name, Args) -> slave_sup() -> process_flag(trap_exit, true), receive - {'EXIT', _, _} -> + {'EXIT', _, _} -> case os:type() of vxworks -> erlang:halt(); @@ -292,7 +292,7 @@ slave_sup() -> ignore end end. - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Index the test case structure @@ -305,7 +305,7 @@ doc(TestCases) when is_list(TestCases) -> io:format(Fd, "<TITLE>Test specification for ~p</TITLE>.~n", [TestCases]), io:format(Fd, "<H1>Test specification for ~p</H1>~n", [TestCases]), io:format(Fd, "Test cases which not are implemented yet are written in <B>bold face</B>.~n~n", []), - + io:format(Fd, "<BR><BR>~n", []), io:format(Fd, "~n<DL>~n", []), do_doc(Fd, TestCases, []), @@ -349,7 +349,7 @@ do_doc(Fd, Module, TestCase, List) -> print_doc(Fd, Mod, Fun, Head) -> case catch (apply(Mod, Fun, [doc])) of - {'EXIT', _} -> + {'EXIT', _} -> io:format(Fd, "<DT>~s</DT>~n", [Head]); Doc when is_list(Doc) -> io:format(Fd, "<DT><U>~s</U><BR><DD>~n", [Head]), @@ -428,10 +428,10 @@ test_driver({Module, TestCase}, Config) -> _ -> log("Eval test case: ~w~n", [{Module, TestCase}]), try timer:tc(?MODULE, eval_test_case, [Module, TestCase, Config]) of - {T, Res} -> + {T, Res} -> log("Tested ~w in ~w sec~n", [TestCase, T div Sec]), {T div Sec, Res} - catch error:function_clause -> + catch error:function_clause -> log("<WARNING> Test case ~w NYI~n", [{Module, TestCase}]), {0, {skip, {Module, TestCase}, "NYI"}} end @@ -472,13 +472,13 @@ get_suite(Module, TestCase, Config) -> %% Returns a list (possibly empty) or the atom 'NYI' get_suite(Mod, {group, Suite}) -> - try + try Groups = Mod:groups(), {_, _, TCList} = lists:keyfind(Suite, 1, Groups), TCList catch _:Reason -> - io:format("Not implemented ~p ~p (~p ~p)~n", + io:format("Not implemented ~p ~p (~p ~p)~n", [Mod,Suite,Reason, erlang:get_stacktrace()]), 'NYI' end; @@ -487,7 +487,7 @@ get_suite(Mod, all) -> {'EXIT', _} -> 'NYI'; List when is_list(List) -> List end; -get_suite(_Mod, _Fun) -> +get_suite(_Mod, _Fun) -> []. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -511,7 +511,7 @@ wait_for_evaluator(Pid, Mod, Fun, Config) -> receive {'EXIT', Pid, {test_case_ok, _PidRes}} -> Errors = flush(), - Res = + Res = case Errors of [] -> ok; Errors -> failed @@ -531,7 +531,7 @@ wait_for_evaluator(Pid, Mod, Fun, Config) -> test_case_evaluator(Mod, Fun, [Config]) -> NewConfig = Mod:init_per_testcase(Fun, Config), - try + try R = apply(Mod, Fun, [NewConfig]), Mod:end_per_testcase(Fun, NewConfig), exit({test_case_ok, R}) @@ -588,7 +588,7 @@ mapl(_Fun, []) -> diskless(Config) -> case lists:keysearch(diskless, 1, Config) of - {value, {diskless, true}} -> + {value, {diskless, true}} -> true; _Else -> false @@ -634,7 +634,7 @@ sync_trans_tid_serial(Nodes) -> select_nodes(N, Config, File, Line) -> prepare_test_case([], N, Config, File, Line). - + prepare_test_case(Actions, N, Config, File, Line) -> NodeList1 = lookup_config(nodes, Config), NodeList2 = lookup_config(nodenames, Config), %% For testserver @@ -666,10 +666,10 @@ do_prepare([delete_schema | Actions], Selected, All, Config, File, Line) -> true -> skip; false -> - Del = fun(Node) -> + Del = fun(Node) -> case mnesia:delete_schema([Node]) of ok -> ok; - {error, {"All nodes not running",_}} -> + {error, {"All nodes not running",_}} -> ok; Else -> ?log("Delete schema error ~p ~n", [Else]) @@ -680,7 +680,7 @@ do_prepare([delete_schema | Actions], Selected, All, Config, File, Line) -> do_prepare(Actions, Selected, All, Config, File, Line); do_prepare([create_schema | Actions], Selected, All, Config, File, Line) -> case diskless(Config) of - true -> + true -> skip; _Else -> case mnesia:create_schema(Selected) of @@ -705,12 +705,12 @@ set_kill_timer(Config) -> case init:get_argument(mnesia_test_timeout) of {ok, _ } -> ok; _ -> - Time0 = + Time0 = case lookup_config(tc_timeout, Config) of [] -> timer:minutes(5); ConfigTime when is_integer(ConfigTime) -> ConfigTime end, - Mul = try + Mul = try test_server:timetrap_scale_factor() catch _:_ -> 1 end, (catch test_server:timetrap(Mul*Time0 + 1000)), @@ -718,7 +718,7 @@ set_kill_timer(Config) -> end. kill_tc(Pid, Time) -> - receive + receive after Time -> case process_info(Pid) of undefined -> ok; @@ -739,10 +739,10 @@ kill_tc(Pid, Time) -> exit(Pid, kill) end end. - + append_unique([], List) -> List; -append_unique([H|R], List) -> +append_unique([H|R], List) -> case lists:member(H, List) of true -> append_unique(R, List); false -> [H | append_unique(R, List)] @@ -751,13 +751,13 @@ append_unique([H|R], List) -> pick_nodes(all, Nodes, File, Line) -> pick_nodes(length(Nodes), Nodes, File, Line); pick_nodes(N, [H | T], File, Line) when N > 0 -> - [H | pick_nodes(N - 1, T, File, Line)]; + [H | pick_nodes(N - 1, T, File, Line)]; pick_nodes(0, _Nodes, _File, _Line) -> []; pick_nodes(N, [], File, Line) -> ?skip("Test case (~p(~p)) ignored: ~p nodes missing~n", [File, Line, N]). - + init_nodes([Node | Nodes], File, Line) -> case net_adm:ping(Node) of pong -> @@ -777,7 +777,7 @@ init_nodes([Node | Nodes], File, Line) -> init_nodes([], _File, _Line) -> []. -%% Returns [Name, Host] +%% Returns [Name, Host] node_to_name_and_host(Node) -> string:tokens(atom_to_list(Node), [$@]). @@ -793,7 +793,7 @@ lookup_config(Key,Config) -> start_appls(Appls, Nodes) -> start_appls(Appls, Nodes, [], [schema]). - + start_appls(Appls, Nodes, Config) -> start_appls(Appls, Nodes, Config, [schema]). @@ -815,9 +815,9 @@ start_appls([], _Nodes, _Config, _Tabs) -> remote_start(mnesia, Config, Nodes) -> case diskless(Config) of - true -> - application_controller:set_env(mnesia, - extra_db_nodes, + true -> + application_controller:set_env(mnesia, + extra_db_nodes, Nodes -- [node()]), application_controller:set_env(mnesia, schema_location, @@ -830,7 +830,7 @@ remote_start(mnesia, Config, Nodes) -> end, {node(), mnesia:start()}; remote_start(Appl, _Config, _Nodes) -> - Res = + Res = case application:start(Appl) of {error, {already_started, Appl}} -> ok; @@ -842,13 +842,13 @@ remote_start(Appl, _Config, _Nodes) -> %% Start Mnesia on all given nodes and wait for specified %% tables to be accessible on each node. The atom all means %% that we should wait for all tables to be loaded -%% +%% %% Returns a list of error tuples {BadNode, mnesia, Reason} start_mnesia(Nodes) -> start_appls([mnesia], Nodes). start_mnesia(Nodes, Tabs) when is_list(Nodes) -> start_appls([mnesia], Nodes, [], Tabs). - + %% Wait for the tables to be accessible from all nodes in the list %% and that all nodes are aware of that the other nodes also ... sync_tables(Nodes, Tabs) -> @@ -924,26 +924,26 @@ verify_nodes([Tab| Tabs], N) -> mnesia:table_info(Tab, ram_copies), Local = mnesia:table_info(Tab, local_content), case Copies -- Nodes of - [] -> + [] -> verify_nodes(Tabs, 0); _Else when Local == true, Nodes /= [] -> verify_nodes(Tabs, 0); Else -> - N2 = + N2 = if - N > 20 -> - log("<>WARNING<> ~w Waiting for table: ~p on ~p ~n", + N > 20 -> + log("<>WARNING<> ~w Waiting for table: ~p on ~p ~n", [node(), Tab, Else]), 0; true -> N+1 - end, + end, timer:sleep(500), verify_nodes([Tab| Tabs], N2) end. %% Nicely stop Mnesia on all given nodes -%% +%% %% Returns a list of error tuples {BadNode, Reason} stop_mnesia(Nodes) when is_list(Nodes) -> stop_appls([mnesia], Nodes). @@ -1047,7 +1047,7 @@ verify_replica_location(Tab, DiscOnly0, Ram0, Disc0, AliveNodes0) -> Read = ignore_dead(DiscOnly ++ Ram ++ Disc, AliveNodes), This = node(), - timer:sleep(100), + timer:sleep(100), S1 = ?match(AliveNodes, lists:sort(mnesia:system_info(running_db_nodes))), S2 = ?match(DiscOnly, lists:sort(mnesia:table_info(Tab, disc_only_copies))), @@ -1080,7 +1080,7 @@ do_remote_activate_debug_fun(From, I, F, C, File, Line) -> timer:sleep(infinity). % Dies whenever the test process dies !! -sort(L) when is_list(L) -> +sort(L) when is_list(L) -> lists:sort(L); sort({atomic, L}) when is_list(L) -> {atomic, lists:sort(L)}; diff --git a/lib/mnesia/test/mnesia_test_lib.hrl b/lib/mnesia/test/mnesia_test_lib.hrl index fc377dbd2c..281634c239 100644 --- a/lib/mnesia/test/mnesia_test_lib.hrl +++ b/lib/mnesia/test/mnesia_test_lib.hrl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 1996-2011. 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 %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -112,7 +112,7 @@ -define(remote_deactivate_debug_fun(N, I), rpc:call(N, mnesia_lib, deactivate_debug_fun, [I, ?FILE, ?LINE])). --define(is_debug_compiled, +-define(is_debug_compiled, case mnesia_lib:is_debug_compiled() of false -> ?skip("Mnesia is not debug compiled, test case ignored.~n", []); @@ -120,7 +120,7 @@ ok end). --define(needs_disc(Config), +-define(needs_disc(Config), case mnesia_test_lib:diskless(Config) of false -> ok; @@ -128,5 +128,5 @@ ?skip("Must have disc, test case ignored.~n", []) end). --define(verify_mnesia(Ups, Downs), +-define(verify_mnesia(Ups, Downs), mnesia_test_lib:verify_mnesia(Ups, Downs, ?FILE, ?LINE)). diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl index ca3f0fbf49..c040d0ca3f 100644 --- a/lib/mnesia/test/mnesia_trans_access_test.erl +++ b/lib/mnesia/test/mnesia_trans_access_test.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 1996-2011. 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 %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -31,22 +31,22 @@ end_per_testcase(Func, Conf) -> -define(receive_messages(Msgs), mnesia_recovery_test:receive_messages(Msgs, ?FILE, ?LINE)). -% First Some debug logging +% First Some debug logging -define(dgb, true). -ifdef(dgb). -define(dl(X, Y), ?verbose("**TRACING: " ++ X ++ "**~n", Y)). --else. +-else. -define(dl(X, Y), ok). -endif. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -all() -> +all() -> [write, read, wread, delete, delete_object, match_object, select, select14, all_keys, transaction, {group, nested_activities}, {group, index_tabs}, {group, index_lifecycle}]. -groups() -> +groups() -> [{nested_activities, [], [basic_nested, {group, nested_transactions}, mix_of_nested_activities]}, @@ -80,128 +80,133 @@ end_per_group(_GroupName, Config) -> write(suite) -> []; write(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = write, - Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:write([]) end)), - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:write({Tab, 2}) end)), - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:write({foo, 2}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:write({Tab, 1, 2})), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = write, + Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:write([]) end)), + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:write({Tab, 2}) end)), + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:write({foo, 2}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:write({Tab, 1, 2})), ?verify_mnesia(Nodes, []). %% Read records read(suite) -> []; read(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = read, - Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - - OneRec = {Tab, 1, 2}, - TwoRec = {Tab, 1, 3}, - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:read([]) end)), - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:read({Tab}) end)), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = read, + Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + + OneRec = {Tab, 1, 2}, + TwoRec = {Tab, 1, 3}, + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:read([]) end)), + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:read({Tab}) end)), ?match({aborted, {bad_type, _}} - , mnesia:transaction(fun() -> mnesia:read(OneRec) end)), - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - ?match({atomic, [OneRec]}, - mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), - ?match({atomic, [OneRec, TwoRec]}, - mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:read({Tab, 1})), + , mnesia:transaction(fun() -> mnesia:read(OneRec) end)), + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + ?match({atomic, [OneRec]}, + mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), + ?match({atomic, [OneRec, TwoRec]}, + mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:read({Tab, 1})), ?verify_mnesia(Nodes, []). %% Read records and set write lock wread(suite) -> []; wread(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = wread, - Schema = [{name, Tab}, {type, set}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - - OneRec = {Tab, 1, 2}, - TwoRec = {Tab, 1, 3}, - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:wread([]) end)), - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:wread({Tab}) end)), + [_N1,N2] = Nodes = ?acquire_nodes(2, Config), + Tab = wread, + Schema = [{name, Tab}, {type, set}, {attributes, [k, v]}, {ram_copies, Nodes}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + + OneRec = {Tab, 1, 2}, + TwoRec = {Tab, 1, 3}, + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:wread([]) end)), + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:wread({Tab}) end)), ?match({aborted, {bad_type, _}} - , mnesia:transaction(fun() -> mnesia:wread(OneRec) end)), - - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - - ?match({atomic, [OneRec]}, - mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), - ?match({atomic, [TwoRec]}, - mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:wread({Tab, 1})), + , mnesia:transaction(fun() -> mnesia:wread(OneRec) end)), + + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + + ?match({atomic, [OneRec]}, + mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), + ?match({atomic, [TwoRec]}, + mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:wread({Tab, 1})), + + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Tab, {Tab, 42, a}, sticky_write) end)), + ?match({atomic, [{Tab,42, a}]}, + rpc:call(N2, mnesia, transaction, [fun() -> mnesia:wread({Tab, 42}) end])), ?verify_mnesia(Nodes, []). %% Delete record delete(suite) -> []; delete(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = delete, - Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:delete([]) end)), - ?match({aborted, {bad_type, _}}, - mnesia:transaction(fun() -> mnesia:delete({Tab}) end)), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = delete, + Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:delete([]) end)), + ?match({aborted, {bad_type, _}}, + mnesia:transaction(fun() -> mnesia:delete({Tab}) end)), ?match({aborted, {bad_type, _}} - , mnesia:transaction(fun() -> mnesia:delete({Tab, 1, 2}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:delete({Tab, 1})), + , mnesia:transaction(fun() -> mnesia:delete({Tab, 1, 2}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:delete({Tab, 1})), ?verify_mnesia(Nodes, []). %% Delete matching record delete_object(suite) -> []; delete_object(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = delete_object, - Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = delete_object, + Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), - OneRec = {Tab, 1, 2}, + OneRec = {Tab, 1, 2}, ?match({aborted, {bad_type, _}}, mnesia:transaction(fun() -> mnesia:delete_object([]) end)), ?match({aborted, {bad_type, _}}, @@ -215,17 +220,17 @@ delete_object(Config) when is_list(Config) -> ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(OneRec) end)), ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - ?match({atomic, ok}, + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(OneRec) end)), - + ?match({'EXIT', {aborted, no_transaction}}, mnesia:delete_object(OneRec)), - ?match({aborted, {bad_type, Tab, _}}, + ?match({aborted, {bad_type, Tab, _}}, mnesia:transaction(fun() -> mnesia:delete_object({Tab, {['_']}, 21}) end)), - ?match({aborted, {bad_type, Tab, _}}, + ?match({aborted, {bad_type, Tab, _}}, mnesia:transaction(fun() -> mnesia:delete_object({Tab, {['$5']}, 21}) end)), ?verify_mnesia(Nodes, []). @@ -234,108 +239,108 @@ delete_object(Config) when is_list(Config) -> match_object(suite) -> []; match_object(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = match, - Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - - OneRec = {Tab, 1, 2}, - OnePat = {Tab, '$1', 2}, - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - ?match({atomic, [OneRec]}, - mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)), - - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:match_object({foo, '$1', 2}) end)), - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:match_object({[], '$1', 2}) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:match_object(OnePat)), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = match, + Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + + OneRec = {Tab, 1, 2}, + OnePat = {Tab, '$1', 2}, + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + ?match({atomic, [OneRec]}, + mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)), + + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:match_object({foo, '$1', 2}) end)), + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:match_object({[], '$1', 2}) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:match_object(OnePat)), ?verify_mnesia(Nodes, []). %% select select(suite) -> []; select(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = match, - Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = match, + Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), - OneRec = {Tab, 1, 2}, - TwoRec = {Tab, 2, 3}, + OneRec = {Tab, 1, 2}, + TwoRec = {Tab, 2, 3}, OnePat = [{{Tab, '$1', 2}, [], ['$_']}], - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), - ?match({atomic, [OneRec]}, - mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)), - - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:select(Tab, {match, '$1', 2}) end)), - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:select(Tab, [{'_', [], '$1'}]) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat)), + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), + ?match({atomic, [OneRec]}, + mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)), + + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:select(Tab, {match, '$1', 2}) end)), + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:select(Tab, [{'_', [], '$1'}]) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat)), ?verify_mnesia(Nodes, []). %% more select select14(suite) -> []; select14(Config) when is_list(Config) -> - [Node1,Node2] = Nodes = ?acquire_nodes(2, Config), - Tab1 = select14_ets, - Tab2 = select14_dets, - Tab3 = select14_remote, - Tab4 = select14_remote_dets, - Schemas = [[{name, Tab1}, {attributes, [k, v]}, {ram_copies, [Node1]}], - [{name, Tab2}, {attributes, [k, v]}, {disc_only_copies, [Node1]}], + [Node1,Node2] = Nodes = ?acquire_nodes(2, Config), + Tab1 = select14_ets, + Tab2 = select14_dets, + Tab3 = select14_remote, + Tab4 = select14_remote_dets, + Schemas = [[{name, Tab1}, {attributes, [k, v]}, {ram_copies, [Node1]}], + [{name, Tab2}, {attributes, [k, v]}, {disc_only_copies, [Node1]}], [{name, Tab3}, {attributes, [k, v]}, {ram_copies, [Node2]}], - [{name, Tab4}, {attributes, [k, v]}, {disc_only_copies, [Node2]}]], + [{name, Tab4}, {attributes, [k, v]}, {disc_only_copies, [Node2]}]], [?match({atomic, ok}, mnesia:create_table(Schema)) || Schema <- Schemas], %% Some Helpers Trans = fun(Fun) -> mnesia:transaction(Fun) end, LoopHelp = fun('$end_of_table',_) -> []; - ({Recs,Cont},Fun) -> + ({Recs,Cont},Fun) -> Sel = mnesia:select(Cont), Recs ++ Fun(Sel, Fun) end, - Loop = fun(Table,Pattern) -> + Loop = fun(Table,Pattern) -> Sel = mnesia:select(Table, Pattern, 1, read), Res = LoopHelp(Sel,LoopHelp), case mnesia:table_info(Table, type) of ordered_set -> Res; _ -> lists:sort(Res) - end + end end, - Test = + Test = fun(Tab) -> - OneRec = {Tab, 1, 2}, - TwoRec = {Tab, 2, 3}, + OneRec = {Tab, 1, 2}, + TwoRec = {Tab, 2, 3}, OnePat = [{{Tab, '$1', 2}, [], ['$_']}], All = [OneRec,TwoRec], AllPat = [{'_', [], ['$_']}], - ?match({atomic, []}, Trans(fun() -> Loop(Tab, OnePat) end)), - ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), - ?match({atomic, [OneRec]}, Trans(fun() -> Loop(Tab, OnePat) end)), - ?match({atomic, All}, Trans(fun() -> Loop(Tab, AllPat) end)), - + ?match({atomic, []}, Trans(fun() -> Loop(Tab, OnePat) end)), + ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(TwoRec) end)), + ?match({atomic, [OneRec]}, Trans(fun() -> Loop(Tab, OnePat) end)), + ?match({atomic, All}, Trans(fun() -> Loop(Tab, AllPat) end)), + {atomic,{_, Cont}} = Trans(fun() -> mnesia:select(Tab, OnePat, 1, read) end), ?match({aborted, wrong_transaction}, Trans(fun() -> mnesia:select(Cont) end)), - - ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, {match, '$1', 2},1,read) end)), - ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, [{'_', [], '$1'}],1,read) end)), - ?match({aborted, _}, Trans(fun() -> mnesia:select(sune) end)), - ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat,1,read)), - ?match({aborted, {badarg,sune}}, + + ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, {match, '$1', 2},1,read) end)), + ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, [{'_', [], '$1'}],1,read) end)), + ?match({aborted, _}, Trans(fun() -> mnesia:select(sune) end)), + ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat,1,read)), + ?match({aborted, {badarg,sune}}, Trans(fun() -> mnesia:select(sune) end)) end, Test(Tab1), @@ -349,28 +354,28 @@ select14(Config) when is_list(Config) -> all_keys(suite) ->[]; all_keys(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = all_keys, - Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - - Write = fun() -> mnesia:write({Tab, 14, 4}) end, - AllKeys = fun() -> mnesia:all_keys(Tab) end, - - ?match({atomic, []}, mnesia:transaction(AllKeys)), - - ?match({atomic, ok}, mnesia:transaction(Write)), - ?match({atomic, [14]}, mnesia:transaction(AllKeys)), - - ?match({atomic, ok}, mnesia:transaction(Write)), - ?match({atomic, [14]}, mnesia:transaction(AllKeys)), - - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:all_keys(foo) end)), - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:all_keys([]) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:all_keys(Tab)), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = all_keys, + Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + + Write = fun() -> mnesia:write({Tab, 14, 4}) end, + AllKeys = fun() -> mnesia:all_keys(Tab) end, + + ?match({atomic, []}, mnesia:transaction(AllKeys)), + + ?match({atomic, ok}, mnesia:transaction(Write)), + ?match({atomic, [14]}, mnesia:transaction(AllKeys)), + + ?match({atomic, ok}, mnesia:transaction(Write)), + ?match({atomic, [14]}, mnesia:transaction(AllKeys)), + + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:all_keys(foo) end)), + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:all_keys([]) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:all_keys(Tab)), ?verify_mnesia(Nodes, []). @@ -436,49 +441,49 @@ transaction(Config) when is_list(Config) -> basic_nested(doc) -> ["Test the basic functionality of nested transactions"]; basic_nested(suite) -> []; basic_nested(Config) when is_list(Config) -> - Nodes = ?acquire_nodes(3, Config), - Args = [{ram_copies, Nodes}, - {attributes, record_info(fields, ntab)}], - ?match({atomic, ok}, mnesia:create_table(ntab, Args)), - do_nested(top), + Nodes = ?acquire_nodes(3, Config), + Args = [{ram_copies, Nodes}, + {attributes, record_info(fields, ntab)}], + ?match({atomic, ok}, mnesia:create_table(ntab, Args)), + do_nested(top), case mnesia_test_lib:diskless(Config) of false -> lists:foreach(fun(N) -> - ?match({atomic, ok}, + ?match({atomic, ok}, mnesia:change_table_copy_type(ntab, N, disc_only_copies)) - end, Nodes), + end, Nodes), do_nested(top); - true -> + true -> skip end, ?verify_mnesia(Nodes, []). do_nested(How) -> F1 = fun() -> - mnesia:write(#ntab{a= 1}), + mnesia:write(#ntab{a= 1}), mnesia:write(#ntab{a= 2}) - end, + end, F2 = fun() -> mnesia:read({ntab, 1}) - end, - ?match({atomic, ok}, mnesia:transaction(F1)), - ?match({atomic, _}, mnesia:transaction(F2)), + end, + ?match({atomic, ok}, mnesia:transaction(F1)), + ?match({atomic, _}, mnesia:transaction(F2)), - ?match({atomic, {aborted, _}}, - mnesia:transaction(fun() -> n_f1(), + ?match({atomic, {aborted, _}}, + mnesia:transaction(fun() -> n_f1(), mnesia:transaction(fun() -> n_f2() end) - end)), + end)), - ?match({atomic, {aborted, _}}, - mnesia:transaction(fun() -> n_f1(), + ?match({atomic, {aborted, _}}, + mnesia:transaction(fun() -> n_f1(), mnesia:transaction(fun() -> n_f3() end) - end)), - ?match({atomic, {atomic, [#ntab{a = 5}]}}, - mnesia:transaction(fun() -> mnesia:write(#ntab{a = 5}), + end)), + ?match({atomic, {atomic, [#ntab{a = 5}]}}, + mnesia:transaction(fun() -> mnesia:write(#ntab{a = 5}), mnesia:transaction(fun() -> n_f4() end) - end)), - Cyclic = fun() -> mnesia:abort({cyclic,a,a,a,a,a}) end, %% Ugly - NodeNotR = fun() -> mnesia:abort({node_not_running, testNode}) end, + end)), + Cyclic = fun() -> mnesia:abort({cyclic,a,a,a,a,a}) end, %% Ugly + NodeNotR = fun() -> mnesia:abort({node_not_running, testNode}) end, TestAbort = fun(Fun) -> case get(restart_counter) of @@ -490,46 +495,46 @@ do_nested(How) -> ok end end, - - ?match({atomic,{atomic,ok}}, + + ?match({atomic,{atomic,ok}}, mnesia:transaction(fun()->mnesia:transaction(TestAbort, [Cyclic])end)), - - ?match({atomic,{atomic,ok}}, + + ?match({atomic,{atomic,ok}}, mnesia:transaction(fun()->mnesia:transaction(TestAbort, [NodeNotR])end)), - + %% Now try the restart thingie case How of - top -> - Pids = [spawn(?MODULE, do_nested, [{spawned, self()}]), - spawn(?MODULE, do_nested, [{spawned, self()}]), - spawn(?MODULE, do_nested, [{spawned, self()}]), - spawn(?MODULE, do_nested, [{spawned, self()}])], - ?match({info, _, _}, mnesia_tm:get_info(2000)), + top -> + Pids = [spawn(?MODULE, do_nested, [{spawned, self()}]), + spawn(?MODULE, do_nested, [{spawned, self()}]), + spawn(?MODULE, do_nested, [{spawned, self()}]), + spawn(?MODULE, do_nested, [{spawned, self()}])], + ?match({info, _, _}, mnesia_tm:get_info(2000)), lists:foreach(fun(P) -> receive {P, ok} -> ok end - end, Pids), + end, Pids), ?match([], [Tab || Tab <- ets:all(), mnesia_trans_store == ets:info(Tab, name)]); - + {spawned, Pid} -> - ?match({info, _, _}, mnesia_tm:get_info(2000)), + ?match({info, _, _}, mnesia_tm:get_info(2000)), Pid ! {self(), ok}, exit(normal) end. n_f1() -> - mnesia:read({ntab, 1}), + mnesia:read({ntab, 1}), mnesia:write(#ntab{a = 3}). n_f2() -> - mnesia:write(#ntab{a = 4}), + mnesia:write(#ntab{a = 4}), erlang:error(exit_here). n_f3() -> - mnesia:write(#ntab{a = 4}), + mnesia:write(#ntab{a = 4}), throw(funky). n_f4() -> @@ -555,24 +560,24 @@ nested_trans_both_dies(Config) when is_list(Config) -> nested_transactions(Config, abort, abort). nested_transactions(Config, Child, Father) -> - [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), + [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), Tab = nested_trans, - Def = + Def = case mnesia_test_lib:diskless(Config) of true -> [{name, Tab}, {ram_copies, Nodes}]; false -> - [{name, Tab}, {ram_copies, [Node1]}, + [{name, Tab}, {ram_copies, [Node1]}, {disc_copies, [Node2]}, {disc_only_copies, [Node3]}] end, ?match({atomic, ok}, mnesia:create_table(Def)), ?match(ok, mnesia:dirty_write({Tab, father, not_updated})), - ?match(ok, mnesia:dirty_write({Tab, child, not_updated})), + ?match(ok, mnesia:dirty_write({Tab, child, not_updated})), ChildOk = fun() -> mnesia:write({Tab, child, updated}) end, - ChildAbort = fun() -> + ChildAbort = fun() -> mnesia:write({Tab, child, updated}), erlang:error(exit_here) end, @@ -616,7 +621,7 @@ nested_transactions(Config, Child, Father) -> ?verify_mnesia(Nodes, []). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -mix_of_nested_activities(doc) -> +mix_of_nested_activities(doc) -> ["Verify that dirty operations in a transaction are handled like ", "normal transactions"]; mix_of_nested_activities(suite) -> []; @@ -624,27 +629,27 @@ mix_of_nested_activities(Config) when is_list(Config) -> [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), Tab = tab, - Def = + Def = case mnesia_test_lib:diskless(Config) of true -> [{ram_copies, Nodes}]; - false -> - [{ram_copies, [Node1]}, - {disc_copies, [Node2]}, + false -> + [{ram_copies, [Node1]}, + {disc_copies, [Node2]}, {disc_only_copies, [Node3]}] end, ?match({atomic, ok}, mnesia:create_table(Tab, [{type,bag}|Def])), - Activities = [transaction, sync_transaction, + Activities = [transaction, sync_transaction, ets, async_dirty, sync_dirty], %% Make a test for all 3000 combinations - Tests = [[A,B,C,D,E] || + Tests = [[A,B,C,D,E] || A <- Activities, B <- Activities, C <- Activities, D <- Activities, E <- Activities], - Foreach = - fun(Test,No) -> + Foreach = + fun(Test,No) -> Result = lists:reverse(Test), ?match({No,Result},{No,catch apply_op({Tab,No},Test)}), No+1 @@ -661,9 +666,9 @@ apply_op(Oid = {Tab,Key},[Type|Next]) -> apply_op(Oid,Next) end)). -check_res(transaction, {atomic,Res}) -> +check_res(transaction, {atomic,Res}) -> Res; -check_res(sync_transaction, {atomic,Res}) -> +check_res(sync_transaction, {atomic,Res}) -> Res; check_res(async_dirty, Res) when is_list(Res) -> Res; @@ -673,11 +678,11 @@ check_res(ets, Res) when is_list(Res) -> Res; check_res(Type,Res) -> ?match(bug,{Type,Res}). - + read_op(Oid) -> case lists:reverse(mnesia:read(Oid)) of [] -> []; - [{_,_,Ops}|_] -> + [{_,_,Ops}|_] -> Ops end. @@ -686,24 +691,24 @@ read_op(Oid) -> index_match_object(suite) -> []; index_match_object(Config) when is_list(Config) -> - [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), - Tab = index_match_object, - Schema = [{name, Tab}, {attributes, [k, v, e]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - ValPos = 3, - BadValPos = ValPos + 2, - ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), - - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:index_match_object({Tab, '$1', 2}, ValPos) end)), - OneRec = {Tab, {1, 1}, 2, {1, 1}}, - OnePat = {Tab, '$1', 2, '_'}, + [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), + Tab = index_match_object, + Schema = [{name, Tab}, {attributes, [k, v, e]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 2, + ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), + + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:index_match_object({Tab, '$1', 2}, ValPos) end)), + OneRec = {Tab, {1, 1}, 2, {1, 1}}, + OnePat = {Tab, '$1', 2, '_'}, BadPat = {Tab, '$1', '$2', '_'}, %% See ref guide - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - Imatch = fun(Patt, Pos) -> + Imatch = fun(Patt, Pos) -> mnesia:transaction(fun() -> lists:sort(mnesia:index_match_object(Patt, Pos)) end) end, ?match({atomic, [OneRec]}, Imatch(OnePat, ValPos)), @@ -711,13 +716,13 @@ index_match_object(Config) when is_list(Config) -> ?match({aborted, _}, Imatch({foo, '$1', 2, '_'}, ValPos)), ?match({aborted, _}, Imatch({[], '$1', 2, '_'}, ValPos)), ?match({aborted, _}, Imatch(BadPat, ValPos)), - ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_match_object(OnePat, ValPos)), + ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_match_object(OnePat, ValPos)), Another = {Tab, {3,1}, 2, {4,4}}, - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Another) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write({Tab, {4, 4}, 3, {4, 4}}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Another) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write({Tab, {4, 4}, 3, {4, 4}}) end)), ?match({atomic, [OneRec]}, Imatch({Tab, {1,1}, 2, {1,1}}, ValPos)), ?match({atomic, [OneRec]}, Imatch({Tab, {1,1}, 2, '$1'}, ValPos)), @@ -727,110 +732,110 @@ index_match_object(Config) when is_list(Config) -> ?match({atomic, [OneRec]}, Imatch({Tab, {'$2', '$1'}, 2, {'_', '$1'}}, ValPos)), ?match({atomic, [OneRec, Another]}, Imatch({Tab, '_', 2, '_'}, ValPos)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write({Tab, 4, 5, {7, 4}}) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write({Tab, 7, 5, {7, 5}}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write({Tab, 4, 5, {7, 4}}) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write({Tab, 7, 5, {7, 5}}) end)), ?match({atomic, [{Tab, 4, 5, {7, 4}}]}, Imatch({Tab, '$1', 5, {'_', '$1'}}, ValPos)), ?match({atomic, [OneRec]}, rpc:call(Node2, mnesia, transaction, - [fun() -> - lists:sort(mnesia:index_match_object({Tab, {1,1}, 2, + [fun() -> + lists:sort(mnesia:index_match_object({Tab, {1,1}, 2, {1,1}}, ValPos)) - end])), + end])), ?verify_mnesia(Nodes, []). %% Read records by using an index index_read(suite) -> []; index_read(Config) when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = index_read, - Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - ValPos = 3, - BadValPos = ValPos + 1, - ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), - - OneRec = {Tab, 1, 2}, - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(OneRec) end)), - ?match({atomic, [OneRec]}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, BadValPos) end)), - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:index_read(foo, 2, ValPos) end)), - ?match({aborted, _}, - mnesia:transaction(fun() -> mnesia:index_read([], 2, ValPos) end)), - - ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_read(Tab, 2, ValPos)), + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = index_read, + Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 1, + ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), + + OneRec = {Tab, 1, 2}, + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(OneRec) end)), + ?match({atomic, [OneRec]}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, BadValPos) end)), + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:index_read(foo, 2, ValPos) end)), + ?match({aborted, _}, + mnesia:transaction(fun() -> mnesia:index_read([], 2, ValPos) end)), + + ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_read(Tab, 2, ValPos)), ?verify_mnesia(Nodes, []). index_update_set(suite) -> []; index_update_set(Config)when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = index_test, - Schema = [{name, Tab}, {attributes, [k, v1, v2, v3]}, {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - ValPos = v1, + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = index_test, + Schema = [{name, Tab}, {attributes, [k, v1, v2, v3]}, {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + ValPos = v1, ValPos2 = v3, - ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), - + ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), + Pat1 = {Tab, '$1', 2, '$2', '$3'}, - Pat2 = {Tab, '$1', '$2', '$3', '$4'}, - - Rec1 = {Tab, 1, 2, 3, 4}, + Pat2 = {Tab, '$1', '$2', '$3', '$4'}, + + Rec1 = {Tab, 1, 2, 3, 4}, Rec2 = {Tab, 2, 2, 13, 14}, - Rec3 = {Tab, 1, 12, 13, 14}, - Rec4 = {Tab, 4, 2, 13, 14}, - - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec1) end)), - ?match({atomic, [Rec1]}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), - - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec2) end)), - {atomic, R1} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), + Rec3 = {Tab, 1, 12, 13, 14}, + Rec4 = {Tab, 4, 2, 13, 14}, + + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec1) end)), + ?match({atomic, [Rec1]}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec2) end)), + {atomic, R1} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec1, Rec2], lists:sort(R1)), - - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec3) end)), - {atomic, R2} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), + + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec3) end)), + {atomic, R2} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec2], lists:sort(R2)), - ?match({atomic, [Rec2]}, - mnesia:transaction(fun() -> mnesia:index_match_object(Pat1, ValPos) end)), - - {atomic, R3} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end), + ?match({atomic, [Rec2]}, + mnesia:transaction(fun() -> mnesia:index_match_object(Pat1, ValPos) end)), + + {atomic, R3} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end), ?match([Rec3, Rec2], lists:sort(R3)), - - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec4) end)), - {atomic, R4} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), + + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec4) end)), + {atomic, R4} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec2, Rec4], lists:sort(R4)), - - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)), - ?match({atomic, [Rec2]}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), - + + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)), + ?match({atomic, [Rec2]}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + ?match({atomic, ok}, mnesia:del_table_index(Tab, ValPos)), ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec4) end)), ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos2)), - - {atomic, R5} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end), + + {atomic, R5} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end), ?match([Rec3, Rec2, Rec4], lists:sort(R5)), - + {atomic, R6} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec2, Rec4], lists:sort(R6)), - + ?match({atomic, []}, mnesia:transaction(fun() -> mnesia:index_read(Tab, 4, ValPos2) end)), {atomic, R7} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 14, ValPos2) end), @@ -857,62 +862,62 @@ index_update_set(Config)when is_list(Config) -> ?match([Rec1], lists:sort(R11)), ?match({atomic, [Rec1]},mnesia:transaction(fun() -> mnesia:index_read(Tab, 4, ValPos2) end)), ?match({atomic, []},mnesia:transaction(fun() -> mnesia:index_read(Tab, 14, ValPos2) end)), - + ?verify_mnesia(Nodes, []). index_update_bag(suite) -> []; index_update_bag(Config)when is_list(Config) -> - [Node1] = Nodes = ?acquire_nodes(1, Config), - Tab = index_test, + [Node1] = Nodes = ?acquire_nodes(1, Config), + Tab = index_test, Schema = [{name, Tab}, {type, bag}, - {attributes, [k, v1, v2, v3]}, - {ram_copies, [Node1]}], - ?match({atomic, ok}, mnesia:create_table(Schema)), - ValPos = v1, + {attributes, [k, v1, v2, v3]}, + {ram_copies, [Node1]}], + ?match({atomic, ok}, mnesia:create_table(Schema)), + ValPos = v1, ValPos2 = v3, - ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), + ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), Pat1 = {Tab, '$1', 2, '$2', '$3'}, - Pat2 = {Tab, '$1', '$2', '$3', '$4'}, + Pat2 = {Tab, '$1', '$2', '$3', '$4'}, - Rec1 = {Tab, 1, 2, 3, 4}, - Rec2 = {Tab, 2, 2, 13, 14}, - Rec3 = {Tab, 1, 12, 13, 14}, - Rec4 = {Tab, 4, 2, 13, 4}, + Rec1 = {Tab, 1, 2, 3, 4}, + Rec2 = {Tab, 2, 2, 13, 14}, + Rec3 = {Tab, 1, 12, 13, 14}, + Rec4 = {Tab, 4, 2, 13, 4}, Rec5 = {Tab, 1, 2, 234, 14}, %% Simple Index - ?match({atomic, []}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec1) end)), - ?match({atomic, [Rec1]}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), - - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec2) end)), + ?match({atomic, []}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec1) end)), + ?match({atomic, [Rec1]}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec2) end)), {atomic, R1} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec1, Rec2], lists:sort(R1)), - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec3) end)), + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec3) end)), {atomic, R2} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec1, Rec2], lists:sort(R2)), {atomic, R3} = mnesia:transaction(fun() -> mnesia:index_match_object(Pat1, ValPos) end), ?match([Rec1, Rec2], lists:sort(R3)), - + {atomic, R4} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end), ?match([Rec1, Rec3, Rec2], lists:sort(R4)), - - ?match({atomic, ok}, - mnesia:transaction(fun() -> mnesia:write(Rec4) end)), - {atomic, R5} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), + + ?match({atomic, ok}, + mnesia:transaction(fun() -> mnesia:write(Rec4) end)), + {atomic, R5} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec1, Rec2, Rec4], lists:sort(R5)), - ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)), + ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)), {atomic, R6} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec1, Rec2], lists:sort(R6)), @@ -922,20 +927,20 @@ index_update_bag(Config)when is_list(Config) -> 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({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({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)), - + %% reset for rest of testcase ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec3) end)), ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec5) end)), @@ -943,19 +948,19 @@ index_update_bag(Config)when is_list(Config) -> ?match([Rec1, Rec2], lists:sort(R6)), %% OTP-6587 - ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec1) end)), - ?match({atomic, [Rec2]}, - mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), + ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec1) end)), + ?match({atomic, [Rec2]}, + mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)), {atomic, R7} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end), ?match([Rec3, Rec2], lists:sort(R7)), - + %% Two indexies ?match({atomic, ok}, mnesia:del_table_index(Tab, ValPos)), ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec1) end)), ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec4) end)), ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos2)), - + {atomic, R8} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end), ?match([Rec1, Rec2, Rec4], lists:sort(R8)), @@ -1001,12 +1006,12 @@ index_update_bag(Config)when is_list(Config) -> index_write(suite) -> []; index_write(doc) -> ["See ticket OTP-8072"]; index_write(Config)when is_list(Config) -> - Nodes = ?acquire_nodes(1, Config), + Nodes = ?acquire_nodes(1, Config), mnesia:create_table(a, [{index, [val]}]), mnesia:create_table(counter, []), CreateIfNonExist = - fun(Index) -> + fun(Index) -> case mnesia:index_read(a, Index, 3) of [] -> Id = mnesia:dirty_update_counter(counter, id, 1), @@ -1017,7 +1022,7 @@ index_write(Config)when is_list(Config) -> Found end end, - + Trans = fun(A) -> mnesia:transaction(CreateIfNonExist, [A]) %% This works better most of the time @@ -1030,9 +1035,9 @@ index_write(Config)when is_list(Config) -> Res = lists:map(Trans, lists:seq(1,10)), Self ! {self(), Res} end, - + Pids = [spawn(Update) || _ <- lists:seq(1,5)], - + Gather = fun(Pid, Acc) -> receive {Pid, Res} -> [Res|Acc] end end, Results = lists:foldl(Gather, [], Pids), Expected = hd(Results), @@ -1075,7 +1080,7 @@ add_table_index(Config, Storage) -> mnesia:add_table_index(Tab, 1)), ?match({aborted, Reason44 } when element(1, Reason44) == bad_type, mnesia:add_table_index(Tab, 0)), - ?match({aborted, Reason45 } when element(1, Reason45) == bad_type, + ?match({aborted, Reason45 } when element(1, Reason45) == bad_type, mnesia:add_table_index(Tab, -1)), ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), ?match({aborted, Reason46 } when element(1, Reason46) == already_exists, @@ -1083,10 +1088,10 @@ add_table_index(Config, Storage) -> NestedFun = fun() -> ?match({aborted, nested_transaction}, - mnesia:add_table_index(Tab, ValPos)), + mnesia:add_table_index(Tab, ValPos)), ok end, - ?match({atomic, ok}, mnesia:transaction(NestedFun)), + ?match({atomic, ok}, mnesia:transaction(NestedFun)), ?verify_mnesia(Nodes, []). create_live_table_index_ram(suite) -> []; @@ -1110,7 +1115,7 @@ create_live_table_index(Config, Storage) -> mnesia:dirty_write({Tab, 1, 2}), Fun = fun() -> - ?match(ok, mnesia:write({Tab, 2, 2})), + ?match(ok, mnesia:write({Tab, 2, 2})), ok end, ?match({atomic, ok}, mnesia:transaction(Fun)), @@ -1133,17 +1138,17 @@ create_live_table_index(Config, Storage) -> end, ?match([{atomic,ok}|_], [Create(N) || N <- lists:seq(1,50)]), - + ?match([], mnesia_test_lib:stop_mnesia([N2,N3])), ?match(ok, rpc:call(N2, mnesia, start, [[{extra_db_nodes,[N1]}]])), ?match(ok, rpc:call(N3, mnesia, start, [[{extra_db_nodes,[N1]}]])), - + ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)), - + ?match({atomic, [{Tab, 1, 2},{Tab, 2, 2}]}, mnesia:transaction(IRead)), - ?match({atomic, [{Tab, 1, 2},{Tab, 2, 2}]}, + ?match({atomic, [{Tab, 1, 2},{Tab, 2, 2}]}, rpc:call(N2, mnesia, transaction, [IRead])), - + ?verify_mnesia(Nodes, []). %% Drop table index @@ -1210,49 +1215,49 @@ idx_schema_changes(Config, Storage) -> ram_copies -> {disc_copies, disc_only_copies} end, - + Write = fun(N) -> mnesia:write({Tab, N, N+50}) - end, - + end, + [mnesia:sync_transaction(Write, [N]) || N <- lists:seq(1, 10)], ?match([{Tab, 1, 51}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 51, Idx])), ?match([{Tab, 1, 51}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 51, Idx])), ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, N1, Storage1)), - + ?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [17]])), ?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [18]])), - + ?match([{Tab, 17, 67}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 67, Idx])), ?match([{Tab, 18, 68}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 68, Idx])), - + ?match({atomic, ok}, mnesia:del_table_copy(Tab, N1)), ?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [11]])), ?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [12]])), - + ?match([{Tab, 11, 61}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 61, Idx])), ?match([{Tab, 12, 62}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 62, Idx])), ?match({atomic, ok}, mnesia:move_table_copy(Tab, N2, N1)), ?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [19]])), ?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [20]])), - + ?match([{Tab, 19, 69}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 69, Idx])), - ?match([{Tab, 20, 70}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 70, Idx])), - + ?match([{Tab, 20, 70}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 70, Idx])), + ?match({atomic, ok}, mnesia:add_table_copy(Tab, N2, Storage)), ?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [13]])), ?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [14]])), - + ?match([{Tab, 13, 63}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 63, Idx])), ?match([{Tab, 14, 64}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 64, Idx])), - + ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, N2, Storage2)), - + ?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [15]])), ?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [16]])), - + ?match([{Tab, 15, 65}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 65, Idx])), ?match([{Tab, 16, 66}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 66, Idx])), |