aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl')
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl380
1 files changed, 0 insertions, 380 deletions
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl
deleted file mode 100644
index 3455a4808a..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl
+++ /dev/null
@@ -1,380 +0,0 @@
-%% ``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 via the world wide web 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.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id: mnesia_index.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
-%% Purpose: Handles index functionality in mnesia
-
--module(mnesia_index).
--export([read/5,
- add_index/5,
- delete_index/3,
- del_object_index/5,
- clear_index/4,
- dirty_match_object/3,
- dirty_select/3,
- dirty_read/3,
- dirty_read2/3,
-
- db_put/2,
- db_get/2,
- db_match_erase/2,
- get_index_table/2,
- get_index_table/3,
-
- tab2filename/2,
- tab2tmp_filename/2,
- init_index/2,
- init_indecies/3,
- del_transient/2,
- del_transient/3,
- del_index_table/3]).
-
--import(mnesia_lib, [verbose/2]).
--include("mnesia.hrl").
-
--record(index, {setorbag, pos_list}).
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
- end.
-
-%% read an object list throuh its index table
-%% we assume that table Tab has index on attribute number Pos
-
-read(Tid, Store, Tab, IxKey, Pos) ->
- ResList = mnesia_locker:ixrlock(Tid, Store, Tab, IxKey, Pos),
- %% Remove all tuples which don't include Ixkey, happens when Tab is a bag
- case val({Tab, setorbag}) of
- bag ->
- mnesia_lib:key_search_all(IxKey, Pos, ResList);
- _ ->
- ResList
- end.
-
-add_index(Index, Tab, Key, Obj, Old) ->
- add_index2(Index#index.pos_list, Index#index.setorbag, 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) ->
- %% 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);
-add_index2([], _, _Tab, _K, _Obj, _) -> ok.
-
-delete_index(Index, Tab, K) ->
- delete_index2(Index#index.pos_list, Tab, K).
-
-delete_index2([{Pos, Ixt} | Tail], Tab, K) ->
- DelObjs = mnesia_lib:db_get(Tab, K),
- del_ixes(Ixt, DelObjs, Pos, K),
- delete_index2(Tail, Tab, K);
-delete_index2([], _Tab, _K) -> ok.
-
-
-del_ixes(_Ixt, [], _Pos, _L) -> ok;
-del_ixes(Ixt, [Obj | Tail], Pos, Key) ->
- db_match_erase(Ixt, {element(Pos, Obj), Key}),
- del_ixes(Ixt, Tail, Pos, Key).
-
-del_object_index(Index, Tab, K, Obj, Old) ->
- del_object_index2(Index#index.pos_list, Index#index.setorbag, Tab, K, Obj, Old).
-
-del_object_index2([], _, _Tab, _K, _Obj, _Old) -> ok;
-del_object_index2([{Pos, Ixt} | Tail], SoB, Tab, K, Obj, Old) ->
- case SoB of
- bag ->
- del_object_bag(Tab, K, Obj, Pos, Ixt, Old);
- _ -> %% If set remove the tuple in index table
- del_ixes(Ixt, [Obj], Pos, K)
- end,
- del_object_index2(Tail, SoB, Tab, K, Obj, Old).
-
-del_object_bag(Tab, Key, Obj, Pos, Ixt, undefined) ->
- Old = mnesia_lib:db_get(Tab, Key),
- del_object_bag(Tab, Key, Obj, Pos, Ixt, Old);
-%% If Tab type is bag we need remove index identifier if Tab
-%% contains less than 2 elements.
-del_object_bag(_Tab, Key, Obj, Pos, Ixt, Old) when length(Old) < 2 ->
- del_ixes(Ixt, [Obj], Pos, Key);
-del_object_bag(_Tab, _Key, _Obj, _Pos, _Ixt, _Old) -> ok.
-
-clear_index(Index, Tab, K, Obj) ->
- clear_index2(Index#index.pos_list, Tab, K, Obj).
-
-clear_index2([], _Tab, _K, _Obj) -> ok;
-clear_index2([{_Pos, Ixt} | Tail], Tab, K, Obj) ->
- db_match_erase(Ixt, Obj),
- clear_index2(Tail, Tab, K, Obj).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-dirty_match_object(Tab, Pat, Pos) ->
- %% Assume that we are on the node where the replica is
- case element(2, Pat) of
- '_' ->
- IxKey = element(Pos, Pat),
- RealKeys = realkeys(Tab, Pos, IxKey),
- merge(RealKeys, Tab, Pat, []);
- _Else ->
- mnesia_lib:db_match_object(Tab, Pat)
- end.
-
-merge([{_IxKey, RealKey} | Tail], Tab, Pat, Ack) ->
- %% Assume that we are on the node where the replica is
- Pat2 = setelement(2, Pat, RealKey),
- Recs = mnesia_lib:db_match_object(Tab, Pat2),
- merge(Tail, Tab, Pat, Recs ++ Ack);
-merge([], _, _, Ack) ->
- Ack.
-
-realkeys(Tab, Pos, IxKey) ->
- Index = get_index_table(Tab, Pos),
- db_get(Index, IxKey). % a list on the form [{IxKey, RealKey1} , ....
-
-dirty_select(Tab, Spec, Pos) ->
- %% Assume that we are on the node where the replica is
- %% Returns the records without applying the match spec
- %% The actual filtering is handled by the caller
- IxKey = element(Pos, Spec),
- RealKeys = realkeys(Tab, Pos, IxKey),
- StorageType = val({Tab, storage_type}),
- lists:append([mnesia_lib:db_get(StorageType, Tab, Key) || Key <- RealKeys]).
-
-dirty_read(Tab, IxKey, Pos) ->
- ResList = mnesia:dirty_rpc(Tab, ?MODULE, dirty_read2,
- [Tab, IxKey, Pos]),
- case val({Tab, setorbag}) of
- bag ->
- %% Remove all tuples which don't include Ixkey
- mnesia_lib:key_search_all(IxKey, Pos, ResList);
- _ ->
- ResList
- end.
-
-dirty_read2(Tab, IxKey, Pos) ->
- Ix = get_index_table(Tab, Pos),
- Keys = db_match(Ix, {IxKey, '$1'}),
- r_keys(Keys, Tab, []).
-
-r_keys([[H]|T],Tab,Ack) ->
- V = mnesia_lib:db_get(Tab, H),
- r_keys(T, Tab, V ++ Ack);
-r_keys([], _, Ack) ->
- Ack.
-
-
-%%%%%%% Creation, Init and deletion routines for index tables
-%% We can have several indexes on the same table
-%% this can be a fairly costly operation if table is *very* large
-
-tab2filename(Tab, Pos) ->
- mnesia_lib:dir(Tab) ++ "_" ++ integer_to_list(Pos) ++ ".DAT".
-
-tab2tmp_filename(Tab, Pos) ->
- mnesia_lib:dir(Tab) ++ "_" ++ integer_to_list(Pos) ++ ".TMP".
-
-init_index(Tab, Storage) ->
- PosList = val({Tab, index}),
- init_indecies(Tab, Storage, PosList).
-
-init_indecies(Tab, Storage, PosList) ->
- case Storage of
- unknown ->
- ignore;
- disc_only_copies ->
- init_disc_index(Tab, PosList);
- ram_copies ->
- make_ram_index(Tab, PosList);
- disc_copies ->
- make_ram_index(Tab, PosList)
- end.
-
-%% works for both ram and disc indexes
-
-del_index_table(_, unknown, _) ->
- ignore;
-del_index_table(Tab, Storage, Pos) ->
- delete_transient_index(Tab, Pos, Storage),
- mnesia_lib:del({Tab, index}, Pos).
-
-del_transient(Tab, Storage) ->
- PosList = val({Tab, index}),
- del_transient(Tab, PosList, Storage).
-
-del_transient(_, [], _) -> done;
-del_transient(Tab, [Pos | Tail], Storage) ->
- delete_transient_index(Tab, Pos, Storage),
- del_transient(Tab, Tail, Storage).
-
-delete_transient_index(Tab, Pos, disc_only_copies) ->
- Tag = {Tab, index, Pos},
- mnesia_monitor:unsafe_close_dets(Tag),
- file:delete(tab2filename(Tab, Pos)),
- del_index_info(Tab, Pos), %% Uses val(..)
- mnesia_lib:unset({Tab, {index, Pos}});
-
-delete_transient_index(Tab, Pos, _Storage) ->
- Ixt = val({Tab, {index, Pos}}),
- ?ets_delete_table(Ixt),
- del_index_info(Tab, Pos),
- mnesia_lib:unset({Tab, {index, Pos}}).
-
-%%%%% misc functions for the index create/init/delete functions above
-
-%% assuming that the file exists.
-init_disc_index(_Tab, []) ->
- done;
-init_disc_index(Tab, [Pos | Tail]) when integer(Pos) ->
- Fn = tab2filename(Tab, Pos),
- IxTag = {Tab, index, Pos},
- file:delete(Fn),
- Args = [{file, Fn}, {keypos, 1}, {type, bag}],
- mnesia_monitor:open_dets(IxTag, Args),
- Storage = disc_only_copies,
- Key = mnesia_lib:db_first(Storage, Tab),
- Recs = mnesia_lib:db_get(Storage, Tab, Key),
- BinSize = size(term_to_binary(Recs)),
- KeysPerChunk = (4000 div BinSize) + 1,
- Init = {start, KeysPerChunk},
- mnesia_lib:db_fixtable(Storage, Tab, true),
- ok = dets:init_table(IxTag, create_fun(Init, Tab, Pos)),
- mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_lib:set({Tab, {index, Pos}}, IxTag),
- add_index_info(Tab, val({Tab, setorbag}), {Pos, {dets, IxTag}}),
- init_disc_index(Tab, Tail).
-
-create_fun(Cont, Tab, Pos) ->
- fun(read) ->
- Data =
- case Cont of
- {start, KeysPerChunk} ->
- mnesia_lib:db_init_chunk(disc_only_copies, Tab, KeysPerChunk);
- '$end_of_table' ->
- '$end_of_table';
- _Else ->
- mnesia_lib:db_chunk(disc_only_copies, Cont)
- end,
- case Data of
- '$end_of_table' ->
- end_of_input;
- {Recs, Next} ->
- IdxElems = [{element(Pos, Obj), element(2, Obj)} || Obj <- Recs],
- {IdxElems, create_fun(Next, Tab, Pos)}
- end;
- (close) ->
- ok
- end.
-
-make_ram_index(_, []) ->
- done;
-make_ram_index(Tab, [Pos | Tail]) ->
- add_ram_index(Tab, Pos),
- make_ram_index(Tab, Tail).
-
-add_ram_index(Tab, Pos) when integer(Pos) ->
- verbose("Creating index for ~w ~n", [Tab]),
- Index = mnesia_monitor:mktab(mnesia_index, [bag, public]),
- Insert = fun(Rec, _Acc) ->
- true = ?ets_insert(Index, {element(Pos, Rec), element(2, Rec)})
- end,
- mnesia_lib:db_fixtable(ram_copies, Tab, true),
- true = ets:foldl(Insert, true, Tab),
- mnesia_lib:db_fixtable(ram_copies, Tab, false),
- mnesia_lib:set({Tab, {index, Pos}}, Index),
- add_index_info(Tab, val({Tab, setorbag}), {Pos, {ram, Index}});
-add_ram_index(_Tab, snmp) ->
- ok.
-
-add_index_info(Tab, Type, IxElem) ->
- Commit = val({Tab, commit_work}),
- case lists:keysearch(index, 1, Commit) of
- false ->
- Index = #index{setorbag = Type,
- pos_list = [IxElem]},
- %% Check later if mnesia_tm is sensative about the order
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit([Index | Commit]));
- {value, Old} ->
- %% We could check for consistency here
- Index = Old#index{pos_list = [IxElem | Old#index.pos_list]},
- NewC = lists:keyreplace(index, 1, Commit, Index),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC))
- end.
-
-del_index_info(Tab, Pos) ->
- Commit = val({Tab, commit_work}),
- case lists:keysearch(index, 1, Commit) of
- false ->
- %% Something is wrong ignore
- skip;
- {value, Old} ->
- case lists:keydelete(Pos, 1, Old#index.pos_list) of
- [] ->
- NewC = lists:keydelete(index, 1, Commit),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC));
- New ->
- Index = Old#index{pos_list = New},
- NewC = lists:keyreplace(index, 1, Commit, Index),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC))
- end
- end.
-
-db_put({ram, Ixt}, V) ->
- true = ?ets_insert(Ixt, V);
-db_put({dets, Ixt}, V) ->
- ok = dets:insert(Ixt, V).
-
-db_get({ram, Ixt}, K) ->
- ?ets_lookup(Ixt, K);
-db_get({dets, Ixt}, K) ->
- dets:lookup(Ixt, K).
-
-db_match_erase({ram, Ixt}, Pat) ->
- true = ?ets_match_delete(Ixt, Pat);
-db_match_erase({dets, Ixt}, Pat) ->
- ok = dets:match_delete(Ixt, Pat).
-
-db_match({ram, Ixt}, Pat) ->
- ?ets_match(Ixt, Pat);
-db_match({dets, Ixt}, Pat) ->
- dets:match(Ixt, Pat).
-
-get_index_table(Tab, Pos) ->
- get_index_table(Tab, val({Tab, storage_type}), Pos).
-
-get_index_table(Tab, ram_copies, Pos) ->
- {ram, val({Tab, {index, Pos}})};
-get_index_table(Tab, disc_copies, Pos) ->
- {ram, val({Tab, {index, Pos}})};
-get_index_table(Tab, disc_only_copies, Pos) ->
- {dets, val({Tab, {index, Pos}})};
-get_index_table(_Tab, unknown, _Pos) ->
- unknown.
-