mnesia.erl

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

ERL
2,142
字号
%% ``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 exports the public interface of the Mnesia DBMS engine-module(mnesia).%-behaviour(mnesia_access).-export([	 %% Start, stop and debugging	 start/0, start/1, stop/0,           % Not for public use	 set_debug_level/1, lkill/0, kill/0, % Not for public use	 ms/0, 	 change_config/2,	 %% Activity mgt	 abort/1, transaction/1, transaction/2, transaction/3,	 sync_transaction/1, sync_transaction/2, sync_transaction/3,	 async_dirty/1, async_dirty/2, sync_dirty/1, sync_dirty/2, ets/1, ets/2,	 activity/2, activity/3, activity/4, % Not for public use	 %% Access within an activity - Lock acquisition	 lock/2, lock/4,	 read_lock_table/1, 	 write_lock_table/1,	 %% Access within an activity - Updates	 write/1, s_write/1, write/3, write/5, 	 delete/1, s_delete/1, delete/3, delete/5, 	 delete_object/1, s_delete_object/1, delete_object/3, delete_object/5, 	 	 %% Access within an activity - Reads	 read/1, wread/1, read/3, read/5,	 match_object/1, match_object/3, match_object/5,	 select/1,select/2,select/3,select/4,select/5,select/6,	 all_keys/1, all_keys/4,	 index_match_object/2, index_match_object/4, index_match_object/6,	 index_read/3, index_read/6,	 first/1, next/2, last/1, prev/2,	 %% Iterators within an activity 	 foldl/3, foldl/4, foldr/3, foldr/4,	 	 %% Dirty access regardless of activities - Updates	 dirty_write/1, dirty_write/2,	 dirty_delete/1, dirty_delete/2,	 dirty_delete_object/1, dirty_delete_object/2,	 dirty_update_counter/2, dirty_update_counter/3,	 %% Dirty access regardless of activities - Read	 dirty_read/1, dirty_read/2,	 dirty_select/2,	 dirty_match_object/1, dirty_match_object/2, dirty_all_keys/1,	 dirty_index_match_object/2, dirty_index_match_object/3,	 dirty_index_read/3, dirty_slot/2, 	 dirty_first/1, dirty_next/2, dirty_last/1, dirty_prev/2, 	 %% Info	 table_info/2, table_info/4, schema/0, schema/1,	 error_description/1, info/0, system_info/1,	 system_info/0,                      % Not for public use	 %% Database mgt	 create_schema/1, delete_schema/1,	 backup/1, backup/2, traverse_backup/4, traverse_backup/6,	 install_fallback/1, install_fallback/2,	 uninstall_fallback/0, uninstall_fallback/1,	 activate_checkpoint/1, deactivate_checkpoint/1,	 backup_checkpoint/2, backup_checkpoint/3, restore/2,	 %% Table mgt	 create_table/1, create_table/2, delete_table/1,	 add_table_copy/3, del_table_copy/2, move_table_copy/3,	 add_table_index/2, del_table_index/2,	 transform_table/3, transform_table/4,	 change_table_copy_type/3,	 read_table_property/2, write_table_property/2, delete_table_property/2,	 change_table_frag/2,	 clear_table/1,	 %% Table load	 dump_tables/1, wait_for_tables/2, force_load_table/1,	 change_table_access_mode/2, change_table_load_order/2,	 set_master_nodes/1, set_master_nodes/2,	 	 %% Misc admin	 dump_log/0, subscribe/1, unsubscribe/1, report_event/1,	 %% Snmp	 snmp_open_table/2, snmp_close_table/1,	 snmp_get_row/2, snmp_get_next_index/2, snmp_get_mnesia_key/2,	 %% Textfile access	 load_textfile/1, dump_to_textfile/1,	 	 %% QLC functions	 table/1, table/2,	 %% Mnemosyne exclusive	 get_activity_id/0, put_activity_id/1, % Not for public use	 %% Mnesia internal functions	 dirty_rpc/4,                          % Not for public use	 has_var/1, fun_select/7, fun_select/10, select_cont/3, dirty_sel_init/5,	 foldl/6, foldr/6,	 %% Module internal callback functions	 raw_table_info/2,                      % Not for public use	 remote_dirty_match_object/2,           % Not for public use	 remote_dirty_select/2                  % Not for public use	]).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%-include("mnesia.hrl").-import(mnesia_lib, [verbose/2]).-define(DEFAULT_ACCESS, ?MODULE).%% Select -define(PATTERN_TO_OBJECT_MATCH_SPEC(Pat), [{Pat,[],['$_']}]).-define(PATTERN_TO_BINDINGS_MATCH_SPEC(Pat), [{Pat,[],['$$']}]).   %% Local function in order to avoid external function callval(Var) ->    case ?catch_val(Var) of	{'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason); 	Value -> Value    end.is_dollar_digits(Var) ->    case atom_to_list(Var) of	[$$ | Digs] -> 	    is_digits(Digs);	_ ->	    false    end.is_digits([Dig | Tail]) ->    if	$0 =< Dig, Dig =< $9 ->	    is_digits(Tail);	true ->	    false    end;is_digits([]) ->    true.has_var(X) when atom(X) ->     if 	X == '_' -> 	    true;	atom(X) -> 	    is_dollar_digits(X);	true  -> 	    false    end;has_var(X) when tuple(X) ->    e_has_var(X, size(X));has_var([H|T]) ->    case has_var(H) of	false -> has_var(T);	Other -> Other    end;has_var(_) -> false.e_has_var(_, 0) -> false;e_has_var(X, Pos) ->    case has_var(element(Pos, X))of	false -> e_has_var(X, Pos-1);	Other -> Other    end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Start and stopstart() ->    {Time , Res} =  timer:tc(application, start, [?APPLICATION, temporary]),        Secs = Time div 1000000,    case Res of 	ok ->	    verbose("Mnesia started, ~p seconds~n",[ Secs]),	    ok;	{error, {already_started, mnesia}} ->	    verbose("Mnesia already started, ~p seconds~n",[ Secs]),	    ok;	{error, R} ->	    verbose("Mnesia failed to start, ~p seconds: ~p~n",[ Secs, R]),	    {error, R}    end.start(ExtraEnv) when list(ExtraEnv) ->    case mnesia_lib:ensure_loaded(?APPLICATION) of	ok ->	    patched_start(ExtraEnv);	Error ->	    Error    end;start(ExtraEnv) ->    {error, {badarg, ExtraEnv}}.patched_start([{Env, Val} | Tail]) when atom(Env) ->    case mnesia_monitor:patch_env(Env, Val) of	{error, Reason} ->	    {error, Reason};	_NewVal ->	    patched_start(Tail)    end;patched_start([Head | _]) ->    {error, {bad_type, Head}};patched_start([]) ->    start().stop() ->    case application:stop(?APPLICATION) of	ok -> stopped;	{error, {not_started, ?APPLICATION}} -> stopped;	Other -> Other    end.change_config(extra_db_nodes, Ns) when list(Ns) ->    mnesia_controller:connect_nodes(Ns);change_config(dc_dump_limit, N) when is_number(N), N > 0 ->    case mnesia_lib:is_running() of	yes ->  	    mnesia_lib:set(dc_dump_limit, N),	    {ok, N};	_ -> 	    {error, {not_started, ?APPLICATION}}    end;change_config(BadKey, _BadVal) ->    {error, {badarg, BadKey}}.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Debuggingset_debug_level(Level) ->     mnesia_subscr:set_debug_level(Level).lkill() ->    mnesia_sup:kill().kill() ->    rpc:multicall(mnesia_sup, kill, []).ms() ->    [     mnesia,     mnesia_backup,     mnesia_bup,     mnesia_checkpoint,     mnesia_checkpoint_sup,     mnesia_controller,     mnesia_dumper,     mnesia_loader,     mnesia_frag,      mnesia_frag_hash,      mnesia_frag_old_hash,      mnesia_index,     mnesia_kernel_sup,     mnesia_late_loader,     mnesia_lib,     mnesia_log,     mnesia_registry,     mnesia_schema,     mnesia_snmp_hook,     mnesia_snmp_sup,     mnesia_subscr,     mnesia_sup,     mnesia_text,     mnesia_tm,     mnesia_recover,     mnesia_locker,     %% Keep these last in the list, so     %% mnesia_sup kills these last     mnesia_monitor,      mnesia_event    ]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Activity mgtabort(Reason) ->     exit({aborted, Reason}).transaction(Fun) ->    transaction(get(mnesia_activity_state), Fun, [], infinity, ?DEFAULT_ACCESS, async).transaction(Fun, Retries) when integer(Retries), Retries >= 0 ->    transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, async);transaction(Fun, Retries) when Retries == infinity ->    transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, async);transaction(Fun, Args) ->    transaction(get(mnesia_activity_state), Fun, Args, infinity, ?DEFAULT_ACCESS, async).transaction(Fun, Args, Retries) ->    transaction(get(mnesia_activity_state), Fun, Args, Retries, ?DEFAULT_ACCESS, async).sync_transaction(Fun) ->    transaction(get(mnesia_activity_state), Fun, [], infinity, ?DEFAULT_ACCESS, sync).sync_transaction(Fun, Retries) when integer(Retries), Retries >= 0 ->    transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, sync);sync_transaction(Fun, Retries) when Retries == infinity ->    transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, sync);sync_transaction(Fun, Args) ->    transaction(get(mnesia_activity_state), Fun, Args, infinity, ?DEFAULT_ACCESS, sync).sync_transaction(Fun, Args, Retries) ->    transaction(get(mnesia_activity_state), Fun, Args, Retries, ?DEFAULT_ACCESS, sync).transaction(State, Fun, Args, Retries, Mod, Kind)   when function(Fun), list(Args), Retries == infinity, atom(Mod) ->    mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);transaction(State, Fun, Args, Retries, Mod, Kind)  when function(Fun), list(Args), integer(Retries), Retries >= 0, atom(Mod) ->    mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);transaction(_State, Fun, Args, Retries, Mod, _Kind) ->    {aborted, {badarg, Fun, Args, Retries, Mod}}.non_transaction(State, Fun, Args, ActivityKind, Mod)   when function(Fun), list(Args), atom(Mod) ->    mnesia_tm:non_transaction(State, Fun, Args, ActivityKind, Mod);non_transaction(_State, Fun, Args, _ActivityKind, _Mod) ->    {aborted, {badarg, Fun, Args}}.async_dirty(Fun) ->    async_dirty(Fun, []).async_dirty(Fun, Args) ->    non_transaction(get(mnesia_activity_state), Fun, Args, async_dirty, ?DEFAULT_ACCESS).sync_dirty(Fun) ->    sync_dirty(Fun, []).sync_dirty(Fun, Args) ->    non_transaction(get(mnesia_activity_state), Fun, Args, sync_dirty, ?DEFAULT_ACCESS).ets(Fun) ->    ets(Fun, []).ets(Fun, Args) ->    non_transaction(get(mnesia_activity_state), Fun, Args, ets, ?DEFAULT_ACCESS).activity(Kind, Fun) ->    activity(Kind, Fun, []).activity(Kind, Fun, Args) when list(Args) ->    activity(Kind, Fun, Args, mnesia_monitor:get_env(access_module));activity(Kind, Fun, Mod) ->    activity(Kind, Fun, [], Mod).activity(Kind, Fun, Args, Mod) ->    State = get(mnesia_activity_state),    case Kind of	ets ->                    non_transaction(State, Fun, Args, Kind, Mod);	async_dirty ->            non_transaction(State, Fun, Args, Kind, Mod);	sync_dirty ->             non_transaction(State, Fun, Args, Kind, Mod);	transaction ->            wrap_trans(State, Fun, Args, infinity, Mod, async);	{transaction, Retries} -> wrap_trans(State, Fun, Args, Retries, Mod, async);	sync_transaction ->            wrap_trans(State, Fun, Args, infinity, Mod, sync);	{sync_transaction, Retries} -> wrap_trans(State, Fun, Args, Retries, Mod, sync);	_ ->                      {aborted, {bad_type, Kind}}    end.wrap_trans(State, Fun, Args, Retries, Mod, Kind) ->    case transaction(State, Fun, Args, Retries, Mod, Kind) of	{atomic, GoodRes} -> GoodRes;	BadRes -> exit(BadRes)    end.	     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Access within an activity - lock acquisition%% Grab a lock on an item in the global lock table%% Item may be any term. Lock may be write or read.%% write lock is set on all the given nodes%% read lock is only set on the first node%% Nodes may either be a list of nodes or one node as an atom%% Mnesia on all Nodes must be connected to each other, but%% it is not neccessary that they are up and running.lock(LockItem, LockKind) ->    case get(mnesia_activity_state) of	{?DEFAULT_ACCESS, Tid, Ts} ->	    lock(Tid, Ts, LockItem, LockKind);	{Mod, Tid, Ts} ->	    Mod:lock(Tid, Ts, LockItem, LockKind);	_ ->	    abort(no_transaction)    end.lock(Tid, Ts, LockItem, LockKind) ->    case element(1, Tid) of	tid ->	    case LockItem of		{record, Tab, Key} ->		    lock_record(Tid, Ts, Tab, Key, LockKind);		{table, Tab} ->		    lock_table(Tid, Ts, Tab, LockKind);		{global, GlobalKey, Nodes} ->		    global_lock(Tid, Ts, GlobalKey, LockKind, Nodes);		_ ->		    abort({bad_type, LockItem})	    end;	_Protocol ->	    []    end.%% Grab a read lock on a whole tableread_lock_table(Tab) ->    lock({table, Tab}, read),    ok.%% Grab a write lock on a whole tablewrite_lock_table(Tab) ->    lock({table, Tab}, write),    ok.

⌨️ 快捷键说明

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