mnesia_lib.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,331 行 · 第 1/3 页

ERL
1,331
字号
%% ``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$%%%% This module contains all sorts of various which doesn't fit%% anywhere else. Basically everything is exported.-module(mnesia_lib).-include("mnesia.hrl").-include_lib("kernel/include/file.hrl").-export([core_file/0]).-export([	 active_tables/0,	 add/2,	 add_list/2,	 add_lsort/2,	 all_nodes/0,%%	 catch_val/1,	 cleanup_tmp_files/1,	 	 copy_file/2,	 copy_holders/1,	 coredump/0,	 coredump/1,	 create_counter/1,	 cs_to_nodes/1,	 cs_to_storage_type/2,	 dets_to_ets/6,	 db_chunk/2,	 db_init_chunk/1,	 db_init_chunk/2,	 db_init_chunk/3,	 db_erase/2,	 db_erase/3,	 db_erase_tab/1,	 db_erase_tab/2,	 db_first/1,	 db_first/2,	 db_last/1,	 db_last/2,	 db_fixtable/3,	 db_get/2,	 db_get/3,	 db_match_erase/2,	 db_match_erase/3,	 db_match_object/2,	 db_match_object/3,	 db_next_key/2,	 db_next_key/3,	 db_prev_key/2,	 db_prev_key/3,	 db_put/2,	 db_put/3,	 db_select/2,	 	 db_select/3,	 db_select_init/4,	 db_select_cont/3,	 db_slot/2,	 db_slot/3,	 db_update_counter/3,	 db_update_counter/4,	 dbg_out/2,	 del/2,	 dets_sync_close/1,	 dets_sync_open/2,	 dets_sync_open/3,	 dir/0,	 dir/1,	 dir_info/0,	 dirty_rpc_error_tag/1,	 dist_coredump/0,	 disk_type/1,	 disk_type/2,	 	 elems/2,	 ensure_loaded/1,	 error/2,	 error_desc/1,	 etype/1,	 exists/1,	 fatal/2,	 get_node_number/0,	 fix_error/1,	 important/2,	 incr_counter/1,	 incr_counter/2,	 intersect/2,	 is_running/0,	 is_running/1,	 is_running_remote/0,	 is_string/1,	 key_search_delete/3,	 key_search_all/3,	 last_error/0,	 local_active_tables/0,	 lock_table/1,	 mkcore/1,	 not_active_here/1,	 other_val/2,	 pad_name/3,	 random_time/2,	 read_counter/1,	 readable_indecies/1,	 remote_copy_holders/1,	 report_fatal/2,	 report_system_event/1,	 running_nodes/0,	 running_nodes/1,	 schema_cs_to_storage_type/2,	 search_delete/2,	 set/2,	 set_counter/2,	 set_local_content_whereabouts/1,	 set_remote_where_to_read/1,	 set_remote_where_to_read/2,	 show/1,	 show/2,	 sort_commit/1,	 storage_type_at_node/2,	 swap_tmp_files/1,	 tab2dat/1,	 tab2dmp/1,	 tab2tmp/1,	 tab2dcd/1,	 tab2dcl/1,	 to_list/1,	 union/2,	 uniq/1,	 unlock_table/1,	 unset/1,	 update_counter/2,	 val/1,	 vcore/0,	 vcore/1,	 verbose/2,	 view/0,	 view/1,	 view/2,	 warning/2,	 is_debug_compiled/0,	 activate_debug_fun/5,	 deactivate_debug_fun/3,	 eval_debug_fun/4,	 scratch_debug_fun/0	]). search_delete(Obj, List) ->    search_delete(Obj, List, [], none).search_delete(Obj, [Obj|Tail], Ack, _Res) ->    search_delete(Obj, Tail, Ack, Obj);search_delete(Obj, [H|T], Ack, Res) ->    search_delete(Obj, T, [H|Ack], Res);search_delete(_, [], Ack, Res) ->    {Res, Ack}.key_search_delete(Key, Pos, TupleList) ->    key_search_delete(Key, Pos, TupleList, none, []).key_search_delete(Key, Pos, [H|T], _Obj, Ack) when element(Pos, H) == Key ->    key_search_delete(Key, Pos, T, H, Ack);key_search_delete(Key, Pos, [H|T], Obj, Ack) ->    key_search_delete(Key, Pos, T, Obj, [H|Ack]);key_search_delete(_, _, [], Obj, Ack) ->    {Obj, Ack}.key_search_all(Key, Pos, TupleList) ->     key_search_all(Key, Pos, TupleList, []).key_search_all(Key, N, [H|T], Ack) when element(N, H) == Key ->    key_search_all(Key, N, T, [H|Ack]);key_search_all(Key, N, [_|T], Ack) ->    key_search_all(Key, N, T, Ack);key_search_all(_, _, [], Ack) -> Ack.intersect(L1, L2) ->    L2 -- (L2 -- L1).elems(I, [H|T]) ->    [element(I, H) | elems(I, T)];elems(_, []) ->    [].%%  sort_commit see to that checkpoint info is always first in %%  commit_work structure the other info don't need to be sorted.sort_commit(List) ->    sort_commit2(List, []).sort_commit2([{checkpoints, ChkpL}| Rest], Acc) ->    [{checkpoints, ChkpL}| Rest] ++ Acc;sort_commit2([H | R], Acc) ->    sort_commit2(R, [H | Acc]);sort_commit2([], Acc) -> Acc.    is_string([H|T]) ->    if	0 =< H, H < 256, integer(H)  -> is_string(T);	true -> false    end;is_string([]) -> true.%%%union([H|L1], L2) ->    case lists:member(H, L2) of	true -> union(L1, L2);	false -> [H | union(L1, L2)]    end;union([], L2) -> L2.uniq([]) ->    [];uniq(List) ->    [H|T] = lists:sort(List),    uniq1(H, T, []).uniq1(H, [H|R], Ack) ->    uniq1(H, R, Ack);uniq1(Old, [H|R], Ack) ->    uniq1(H, R, [Old|Ack]);uniq1(Old, [], Ack) ->    [Old| Ack].to_list(X) when list(X) -> X;to_list(X) -> atom_to_list(X).all_nodes() ->    Ns = mnesia:system_info(db_nodes) ++	mnesia:system_info(extra_db_nodes),    mnesia_lib:uniq(Ns).running_nodes() ->    running_nodes(all_nodes()).running_nodes(Ns) ->    {Replies, _BadNs} = rpc:multicall(Ns, ?MODULE, is_running_remote, []),    [N || {GoodState, N} <- Replies, GoodState == true].is_running_remote() ->    IsRunning = is_running(),    {IsRunning == yes, node()}.is_running(Node) when atom(Node) ->    case rpc:call(Node, ?MODULE, is_running, []) of	{badrpc, _} -> no;	X -> X    end.is_running() ->    case ?catch_val(mnesia_status) of	{'EXIT', _} -> no;	running -> yes;	starting -> starting;	stopping -> stopping    end.show(X) ->    show(X, []).show(F, A) ->    io:format(user, F, A).pad_name([Char | Chars], Len, Tail) ->    [Char | pad_name(Chars, Len - 1, Tail)];pad_name([], Len, Tail) when Len =< 0 ->    Tail;pad_name([], Len, Tail) ->    [$ | pad_name([], Len - 1, Tail)].    %% Some utility functions .....active_here(Tab) ->    case val({Tab, where_to_read}) of	Node when Node == node() -> true;	_ -> false    end.not_active_here(Tab) ->    not active_here(Tab).exists(Fname) ->    case file:rawopen(Fname, read) of	{ok, F} ->file:close(F), true;	_ -> false    end.dir() -> mnesia_monitor:get_env(dir).dir(Fname) ->    filename:join([dir(), to_list(Fname)]).tab2dat(Tab) ->  %% DETS files     dir(lists:concat([Tab, ".DAT"])).tab2tmp(Tab) ->    dir(lists:concat([Tab, ".TMP"])).tab2dmp(Tab) ->  %% Dumped ets tables    dir(lists:concat([Tab, ".DMP"])).tab2dcd(Tab) ->  %% Disc copies data    dir(lists:concat([Tab, ".DCD"])).tab2dcl(Tab) ->  %% Disc copies log    dir(lists:concat([Tab, ".DCL"])).storage_type_at_node(Node, Tab) ->    search_key(Node, [{disc_copies, val({Tab, disc_copies})},		      {ram_copies, val({Tab, ram_copies})},		      {disc_only_copies, val({Tab, disc_only_copies})}]).cs_to_storage_type(Node, Cs) ->    search_key(Node, [{disc_copies, Cs#cstruct.disc_copies},		      {ram_copies, Cs#cstruct.ram_copies},		      {disc_only_copies, Cs#cstruct.disc_only_copies}]).schema_cs_to_storage_type(Node, Cs) ->    case cs_to_storage_type(Node, Cs) of	unknown when Cs#cstruct.name == schema -> ram_copies;	Other -> Other    end.search_key(Key, [{Val, List} | Tail]) ->    case lists:member(Key, List) of	true -> Val;	false -> search_key(Key, Tail)    end;search_key(_Key, []) ->    unknown.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ops, we've got some global variables here :-)%% They are%%%%   {Tab, setorbag}, -> set | bag%%   {Tab, storage_type}       -> disc_copies |ram_copies | unknown (**)%%   {Tab, disc_copies}        -> node list  (from schema)%%   {Tab, ram_copies}, -> node list  (from schema)%%   {Tab, arity}, -> number%%   {Tab, attributes}, -> atom list%%   {Tab, wild_pattern}, -> record tuple with '_'s%%   {Tab, {index, Pos}}       -> ets table%%   {Tab, index}              -> integer list%%   {Tab, cstruct}            -> cstruct  structure%%%%   The following fields are dynamic according to the%%   the current node/table situation%%   {Tab, where_to_write}      -> node list%%   {Tab, where_to_read}       -> node | nowhere%%%%   {schema, tables}                    -> tab list%%   {schema, local_tables}              -> tab list  (**)%%%%   {current, db_nodes}                  -> node list%%%%   dir                                  -> directory path (**)%%   mnesia_status                        -> status | running | stopping (**)%%   (**) ==   (Different on all nodes)%%val(Var) ->    case ?catch_val(Var) of	{'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_); 	_VaLuE_ -> _VaLuE_     end.set(Var, Val) ->    ?ets_insert(mnesia_gvar, {Var, Val}).unset(Var) ->    ?ets_delete(mnesia_gvar, Var).other_val(Var, Other) ->    case Var of	{_, where_to_read} -> nowhere;	{_, where_to_write} -> [];	{_, active_replicas} -> [];	_ ->	    pr_other(Var, Other)    end.pr_other(Var, Other) ->    Why = 	case is_running() of	    no -> {node_not_running, node()};	    _ -> {no_exists, Var}	end,    verbose("~p (~p) val(mnesia_gvar, ~w) -> ~p ~p ~n",	    [self(), process_info(self(), registered_name),	     Var, Other, Why]),    case Other of	{badarg, [{ets, lookup_element, _}|_]} ->	    exit(Why);	_ ->	    erlang:fault(Why)    end.%% Some functions for list valued variablesadd(Var, Val) ->    L = val(Var),    set(Var, [Val | lists:delete(Val, L)]).add_list(Var, List) ->    L = val(Var),    set(Var, union(L, List)).del(Var, Val) ->    L = val(Var),    set(Var, lists:delete(Val, L)).%% LSort -> [node()| Sorted] == Locker sortedadd_lsort(Var, Val) when node() == Val ->    L = val(Var),    set(Var, [Val | lists:delete(Val, L)]);add_lsort(Var,Val) ->    case val(Var) of	[Head|Rest] when Head == node() ->	    set(Var,[Head|lsort_add(Val,Rest)]);	List ->	    set(Var,lsort_add(Val,List))    end.lsort_add(Val,List) ->    case ordsets:is_element(Val,List) of	true -> List;	false -> ordsets:add_element(Val,List)    end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?