diff options
Diffstat (limited to 'lib/mnesia/test')
-rw-r--r-- | lib/mnesia/test/Makefile | 40 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_atomicity_test.erl | 96 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_consistency_test.erl | 24 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_dirty_access_test.erl | 5 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_evil_coverage_test.erl | 56 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_frag_hash_test.erl | 94 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_install_test.erl | 2 | ||||
-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 | 845 |
10 files changed, 721 insertions, 559 deletions
diff --git a/lib/mnesia/test/Makefile b/lib/mnesia/test/Makefile index ae4c9626c7..509dddc85d 100644 --- a/lib/mnesia/test/Makefile +++ b/lib/mnesia/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2011. All Rights Reserved. +# Copyright Ericsson AB 1996-2012. 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 @@ -52,24 +52,29 @@ MODULES= \ mnesia_cost \ mnesia_dbn_meters -MnesiaExamplesDir := ../examples +DocExamplesDir := ../doc/src/ -ExampleModules = \ +DocExampleModules = \ company \ company_o \ - bup \ - mnesia_meter \ - mnesia_tpcb -ExamplesHrl = \ + bup + +DocExamplesHrl = \ company.hrl \ company_o.hrl -ERL_FILES= $(MODULES:%=%.erl) $(ExampleModules:%=$(MnesiaExamplesDir)/%.erl) +ExamplesDir := ../examples/ + +ExampleModules = \ + mnesia_meter \ + mnesia_tpcb -HRL_FILES= mnesia_test_lib.hrl $(ExamplesHrl:%=$(MnesiaExamplesDir)/%) +ERL_FILES= $(MODULES:%=%.erl) $(DocExampleModules:%=$(DocExamplesDir)/%.erl) $(ExampleModules:%=$(ExamplesDir)/%.erl) + +HRL_FILES= mnesia_test_lib.hrl $(DocExamplesHrl:%=$(DocExamplesDir)/%) TARGET_FILES= \ - $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(ExampleModules:%=$(EBIN)/%.$(EMULATOR)) + $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(DocExampleModules:%=$(EBIN)/%.$(EMULATOR)) $(ExampleModules:%=$(EBIN)/%.$(EMULATOR)) INSTALL_PROGS= $(TARGET_FILES) @@ -91,7 +96,10 @@ EBIN = . tests debug opt: $(TARGET_FILES) -$(EBIN)/%.beam: $(MnesiaExamplesDir)/%.erl +$(EBIN)/%.beam: $(DocExamplesDir)/%.erl + $(ERLC) -bbeam $(ERL_COMPILE_FLAGS) -o$(EBIN) $< + +$(EBIN)/%.beam: $(ExamplesDir)/%.erl $(ERLC) -bbeam $(ERL_COMPILE_FLAGS) -o$(EBIN) $< clean: @@ -108,11 +116,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt release_tests_spec: opt - $(INSTALL_DIR) $(RELSYSDIR) - $(INSTALL_DATA) mnesia.spec mnesia.cover $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) - $(INSTALL_SCRIPT) mt $(INSTALL_PROGS) $(RELSYSDIR) -# chmod -R u+w $(RELSYSDIR) -# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + $(INSTALL_DIR) "$(RELSYSDIR)" + $(INSTALL_DATA) mnesia.spec mnesia.cover $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)" + $(INSTALL_SCRIPT) mt $(INSTALL_PROGS) "$(RELSYSDIR)" +# chmod -R u+w "$(RELSYSDIR)" +# @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) release_docs_spec: 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_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl index f38e13f3a2..922b89ec2b 100644 --- a/lib/mnesia/test/mnesia_consistency_test.erl +++ b/lib/mnesia/test/mnesia_consistency_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. 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 @@ -100,7 +100,7 @@ groups() -> {group, updates_during_checkpoint_iteration}, {group, load_table_with_activated_checkpoint}, {group, - add_table_copy_to_table_with_activated_checkpoint}]}, + add_table_copy_to_table_checkpoint}]}, {updates_during_checkpoint_activation, [], [updates_during_checkpoint_activation_2_ram, updates_during_checkpoint_activation_2_disc, @@ -116,10 +116,10 @@ groups() -> [load_table_with_activated_checkpoint_ram, load_table_with_activated_checkpoint_disc, load_table_with_activated_checkpoint_disc_only]}, - {add_table_copy_to_table_with_activated_checkpoint, [], - [add_table_copy_to_table_with_activated_checkpoint_ram, - add_table_copy_to_table_with_activated_checkpoint_disc, - add_table_copy_to_table_with_activated_checkpoint_disc_only]}, + {add_table_copy_to_table_checkpoint, [], + [add_table_copy_to_table_checkpoint_ram, + add_table_copy_to_table_checkpoint_disc, + add_table_copy_to_table_checkpoint_disc_only]}, {backup_consistency, [], [{group, interupted_install_fallback}, {group, interupted_uninstall_fallback}, @@ -952,16 +952,16 @@ view(Source, Mod) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -add_table_copy_to_table_with_activated_checkpoint_ram(suite) -> []; -add_table_copy_to_table_with_activated_checkpoint_ram(Config) when is_list(Config) -> +add_table_copy_to_table_checkpoint_ram(suite) -> []; +add_table_copy_to_table_checkpoint_ram(Config) when is_list(Config) -> add_table_copy_to_table_with_activated_checkpoint(ram_copies, Config). -add_table_copy_to_table_with_activated_checkpoint_disc(suite) -> []; -add_table_copy_to_table_with_activated_checkpoint_disc(Config) when is_list(Config) -> +add_table_copy_to_table_checkpoint_disc(suite) -> []; +add_table_copy_to_table_checkpoint_disc(Config) when is_list(Config) -> add_table_copy_to_table_with_activated_checkpoint(disc_copies, Config). -add_table_copy_to_table_with_activated_checkpoint_disc_only(suite) -> []; -add_table_copy_to_table_with_activated_checkpoint_disc_only(Config) when is_list(Config) -> +add_table_copy_to_table_checkpoint_disc_only(suite) -> []; +add_table_copy_to_table_checkpoint_disc_only(Config) when is_list(Config) -> add_table_copy_to_table_with_activated_checkpoint(disc_only_copies, Config). add_table_copy_to_table_with_activated_checkpoint(Type,Config) -> diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl index abbdab48c0..6017092095 100644 --- a/lib/mnesia/test/mnesia_dirty_access_test.erl +++ b/lib/mnesia/test/mnesia_dirty_access_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. 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 @@ -527,6 +527,9 @@ dirty_index_update_bag(Config, Storage) -> ?match(ok, mnesia:dirty_write(Rec1)), ?match([Rec1], mnesia:dirty_index_read(Tab, 2, ValPos)), + ?match(ok, mnesia:dirty_delete_object(Rec5)), + ?match([Rec1], mnesia:dirty_index_read(Tab, 2, ValPos)), + ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec2) end)), R1 = mnesia:dirty_index_read(Tab, 2, ValPos), ?match([Rec1, Rec2], lists:sort(R1)), diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl index 17d6c6c212..64b61288ef 100644 --- a/lib/mnesia/test/mnesia_evil_coverage_test.erl +++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl @@ -37,7 +37,8 @@ end_per_testcase(Func, Conf) -> all() -> [system_info, table_info, error_description, db_node_lifecycle, evil_delete_db_node, start_and_stop, - checkpoint, table_lifecycle, add_copy_conflict, + checkpoint, table_lifecycle, storage_options, + add_copy_conflict, add_copy_when_going_down, replica_management, schema_availability, local_content, {group, table_access_modifications}, replica_location, @@ -244,7 +245,7 @@ db_node_lifecycle(Config) when is_list(Config) -> ?match([], mnesia_test_lib:start_mnesia(AllNodes)), ?match([SNs, SNs, SNs], - lists:map({lists, sort}, + lists:map(fun lists:sort/1, element(1, rpc:multicall(AllNodes, mnesia, table_info, [schema, disc_copies])))), @@ -259,7 +260,7 @@ db_node_lifecycle(Config) when is_list(Config) -> mnesia:change_table_copy_type(schema, Node2, disc_copies)), ?match([SNs, SNs, SNs], - lists:map({lists, sort}, + lists:map(fun lists:sort/1, element(1, rpc:multicall(AllNodes, mnesia, table_info, [schema, disc_copies])))), @@ -462,7 +463,7 @@ table_lifecycle(Config) when is_list(Config) -> ?match({atomic, ok}, mnesia:create_table([{name, already_exists}, {ram_copies, [Node1]}])), ?match({aborted, Reason23 } when element(1, Reason23) ==already_exists, - mnesia:create_table([{name, already_exists}, + mnesia:create_table([{name, already_exists}, {ram_copies, [Node1]}])), ?match({aborted, Reason21 } when element(1, Reason21) == bad_type, mnesia:create_table([{name, bad_node}, {ram_copies, ["foo"]}])), @@ -520,12 +521,57 @@ table_lifecycle(Config) when is_list(Config) -> ?match({atomic, ok}, mnesia:create_table([{name, create_with_index}, {index, [3]}, {ram_copies, [Node1]}])), - ets:new(ets_table, [named_table]), + ets:new(ets_table, [named_table]), ?match({aborted, _}, mnesia:create_table(ets_table, [{ram_copies, Nodes}])), + ?match({aborted, _}, mnesia:create_table(ets_table, [{ram_copies, [Node1]}])), + ets:delete(ets_table), + ?match({atomic, ok}, mnesia:create_table(ets_table, [{ram_copies, [Node1]}])), + ?match(Node1, rpc:call(Node1, mnesia_lib, val, [{ets_table,where_to_read}])), + ?match(Node1, rpc:call(Node2, mnesia_lib, val, [{ets_table,where_to_read}])), + ?match({atomic, ok}, mnesia:change_table_copy_type(ets_table, Node1, disc_only_copies)), + ?match(Node1, rpc:call(Node2, mnesia_lib, val, [{ets_table,where_to_read}])), + + ?verify_mnesia(Nodes, []). + + +storage_options(suite) -> []; +storage_options(Config) when is_list(Config) -> + [N1,N2,N3] = Nodes = ?acquire_nodes(3, Config), + + ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,foobar}]}])), + ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,[foobar]}]}])), + ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,[duplicate_bag]}]}])), + ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{dets,[{type,bag}]}]}])), + + ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [N1]}, + {disc_only_copies, [N2]}, + {storage_properties, + [{ets,[compressed]}, + {dets, [{auto_save, 5000}]} ]}])), + ?match(true, ets:info(a, compressed)), + ?match(5000, rpc:call(N2, dets, info, [a, auto_save])), + ?match(ok, mnesia:dirty_write({a,1,1})), + ?match([{a,1,1}], mnesia:dirty_read({a,1})), + mnesia:dump_log(), + W2C1 = [{N2, disc_only_copies}, {N1, ram_copies}], + ?match(W2C1, lists:sort(rpc:call(N2, mnesia_lib, val, [{a, where_to_commit}]))), + ?match(W2C1, lists:sort(rpc:call(N3, mnesia_lib, val, [{a, where_to_commit}]))), + ?match({atomic,ok}, mnesia:change_table_copy_type(a, N1, disc_only_copies)), + W2C2 = [{N2, disc_only_copies}, {N1, disc_only_copies}], + ?match(W2C2, lists:sort(rpc:call(N2, mnesia_lib, val, [{a, where_to_commit}]))), + ?match(W2C2, lists:sort(rpc:call(N3, mnesia_lib, val, [{a, where_to_commit}]))), + ?match(undefined, ets:info(a, compressed)), + ?match(5000, dets:info(a, auto_save)), + ?match({atomic,ok}, mnesia:change_table_copy_type(a, N1, disc_copies)), + ?match(true, ets:info(a, compressed)), ?verify_mnesia(Nodes, []). + + + + add_copy_conflict(suite) -> []; add_copy_conflict(doc) -> ["Verify that OTP-5065 doesn't happen again, whitebox testing"]; diff --git a/lib/mnesia/test/mnesia_frag_hash_test.erl b/lib/mnesia/test/mnesia_frag_hash_test.erl new file mode 100644 index 0000000000..095d25e74f --- /dev/null +++ b/lib/mnesia/test/mnesia_frag_hash_test.erl @@ -0,0 +1,94 @@ +-module(mnesia_frag_hash_test). + +-export([test/0]). + +-define(NUM_FRAGS, 20). +-define(NUM_KEYS, 10000). + +-record(hash_state, + {n_fragments, + next_n_to_split, + n_doubles, + function}). + +% OLD mnesia_frag_hash:key_to_frag_number/2. +old_key_to_frag_number(#hash_state{function = phash, next_n_to_split = SplitN, n_doubles = L}, Key) -> + P = SplitN, + A = erlang:phash(Key, power2(L)), + if + A < P -> + erlang:phash(Key, power2(L + 1)); + true -> + A + end; +old_key_to_frag_number(#hash_state{function = phash2, next_n_to_split = SplitN, n_doubles = L}, Key) -> + P = SplitN, + A = erlang:phash2(Key, power2(L)) + 1, + if + A < P -> + erlang:phash2(Key, power2(L + 1)) + 1; + true -> + A + end; +old_key_to_frag_number(OldState, Key) -> + State = convert_old_state(OldState), + old_key_to_frag_number(State, Key). + + +% NEW mnesia_frag_hash:key_to_frag_number/2. +new_key_to_frag_number(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) -> + A = erlang:phash(Key, power2(L + 1)), + if + A > N -> + A - power2(L); + true -> + A + end; +new_key_to_frag_number(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) -> + A = erlang:phash2(Key, power2(L + 1)) + 1, + if + A > N -> + A - power2(L); + true -> + A + end; +new_key_to_frag_number(OldState, Key) -> + State = convert_old_state(OldState), + new_key_to_frag_number(State, Key). + + +% Helpers for key_to_frag_number functions. + +power2(Y) -> + 1 bsl Y. % trunc(math:pow(2, Y)). + +convert_old_state({hash_state, N, P, L}) -> + #hash_state{n_fragments = N, + next_n_to_split = P, + n_doubles = L, + function = phash}. + + +test() -> + test2(mnesia_frag_hash:init_state(undefined, undefined)), % phash2 + test2({hash_state, 1, 1, 0}). % phash + +test2(I) -> + test_keys(I), + lists:foldl( + fun(_, S) -> test_frag(S) end, + I, lists:seq(1, ?NUM_FRAGS)), + ok. + +test_frag(State) -> + {State2,_,_} = mnesia_frag_hash:add_frag(State), + test_keys(State2), + State2. + +test_keys(State) -> + [test_key(State, Key) || Key <- lists:seq(1, ?NUM_KEYS)]. + +test_key(State, Key) -> + Old = old_key_to_frag_number(State, Key), + New = new_key_to_frag_number(State, Key), + Old = New. diff --git a/lib/mnesia/test/mnesia_install_test.erl b/lib/mnesia/test/mnesia_install_test.erl index 3a2d44aa95..06d53d3912 100644 --- a/lib/mnesia/test/mnesia_install_test.erl +++ b/lib/mnesia/test/mnesia_install_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% 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 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..157e441b27 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. -%% +%% +%% Copyright Ericsson AB 1996-2012. 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,66 @@ 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:delete_object(Rec5) 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 +931,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 +952,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 +1010,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 +1026,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 +1039,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 +1084,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 +1092,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 +1119,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 +1142,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 +1219,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])), |