aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gudmundsson <[email protected]>2015-09-16 11:46:33 +0200
committerDan Gudmundsson <[email protected]>2015-09-16 11:46:33 +0200
commite23ea97d7dce3c12f54f06cb90354a0b3a55d073 (patch)
tree69cd423074ce66091812204a95d2a41d2a39e2cf
parentf0841ed29c96220d1a7c0b2ce7fa19795ec20816 (diff)
parent027726da70f31541bd3c4813bf464489a808ae91 (diff)
downloadotp-e23ea97d7dce3c12f54f06cb90354a0b3a55d073.tar.gz
otp-e23ea97d7dce3c12f54f06cb90354a0b3a55d073.tar.bz2
otp-e23ea97d7dce3c12f54f06cb90354a0b3a55d073.zip
Merge branch 'dgud/mnesia/index-timing/OTP-12972' into maint
* dgud/mnesia/index-timing/OTP-12972: mnesia: Improve index updates
-rw-r--r--lib/mnesia/src/mnesia_index.erl27
-rw-r--r--lib/mnesia/test/mnesia_dirty_access_test.erl19
2 files changed, 35 insertions, 11 deletions
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index 81ed5a8f1a..0c882c0df6 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -70,17 +70,24 @@ add_index(Index, Tab, Key, Obj, Old) ->
add_index2([{Pos, Ixt} |Tail], bag, Tab, K, Obj, OldRecs) ->
db_put(Ixt, {element(Pos, Obj), K}),
add_index2(Tail, bag, Tab, K, Obj, OldRecs);
-add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs) ->
+add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs0) ->
%% Remove old tuples in index if Tab is updated
- case OldRecs of
- undefined ->
- Old = mnesia_lib:db_get(Tab, K),
- del_ixes(Ixt, Old, Pos, K);
- Old ->
- del_ixes(Ixt, Old, Pos, K)
- end,
- db_put(Ixt, {element(Pos, Obj), K}),
- add_index2(Tail, Type, Tab, K, Obj, OldRecs);
+ OldRecs1 = case OldRecs0 of
+ undefined -> mnesia_lib:db_get(Tab, K);
+ _ -> OldRecs0
+ end,
+ IdxVal = element(Pos, Obj),
+ case [Old || Old <- OldRecs1, element(Pos, Old) =/= IdxVal] of
+ [] when OldRecs1 =:= [] -> %% Write
+ db_put(Ixt, {element(Pos, Obj), K}),
+ add_index2(Tail, Type, Tab, K, Obj, OldRecs0);
+ [] -> %% when OldRecs1 =/= [] Update without modifying index field
+ add_index2(Tail, Type, Tab, K, Obj, OldRecs0);
+ OldRecs -> %% Update
+ db_put(Ixt, {element(Pos, Obj), K}),
+ del_ixes(Ixt, OldRecs, Pos, K),
+ add_index2(Tail, Type, Tab, K, Obj, OldRecs0)
+ end;
add_index2([], _, _Tab, _K, _Obj, _) -> ok.
delete_index(Index, Tab, K) ->
diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl
index 89aff2b3b8..0d57e5a1b1 100644
--- a/lib/mnesia/test/mnesia_dirty_access_test.erl
+++ b/lib/mnesia/test/mnesia_dirty_access_test.erl
@@ -401,9 +401,26 @@ dirty_index_read(Config, Storage) ->
?match({'EXIT', _}, mnesia:dirty_index_read(Tab, 2, BadValPos)),
?match({'EXIT', _}, mnesia:dirty_index_read(foo, 2, ValPos)),
?match({'EXIT', _}, mnesia:dirty_index_read([], 2, ValPos)),
-
+
+ mnesia:dirty_write({Tab, 5, 1}),
+ ?match(ok, index_read_loop(Tab, 0)),
+
?verify_mnesia(Nodes, []).
+
+index_read_loop(Tab, N) when N =< 1000 ->
+ spawn_link(fun() ->
+ mnesia:transaction(fun() -> mnesia:write({Tab, 5, 1}) end)
+ end),
+ case mnesia:dirty_match_object({Tab, '_', 1}) of
+ [{Tab, 5, 1}] ->
+ index_read_loop(Tab, N+1);
+ Other -> {N, Other}
+ end;
+index_read_loop(_, _) ->
+ ok.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%