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 + -
显示快捷键?