mnesia_schema.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 2,011 行 · 第 1/5 页
ERL
2,011 行
_Ns -> verify_cstruct(Cs2), [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)}| remove_node_from_tabs(Rest, Node)] end end.new_cs(Cs, Node, ram_copies, add) -> Cs#cstruct{ram_copies = opt_add(Node, Cs#cstruct.ram_copies)};new_cs(Cs, Node, disc_copies, add) -> Cs#cstruct{disc_copies = opt_add(Node, Cs#cstruct.disc_copies)};new_cs(Cs, Node, disc_only_copies, add) -> Cs#cstruct{disc_only_copies = opt_add(Node, Cs#cstruct.disc_only_copies)};new_cs(Cs, Node, ram_copies, del) -> Cs#cstruct{ram_copies = lists:delete(Node , Cs#cstruct.ram_copies)};new_cs(Cs, Node, disc_copies, del) -> Cs#cstruct{disc_copies = lists:delete(Node , Cs#cstruct.disc_copies)};new_cs(Cs, Node, disc_only_copies, del) -> Cs#cstruct{disc_only_copies = lists:delete(Node , Cs#cstruct.disc_only_copies)};new_cs(Cs, _Node, Storage, _Op) -> mnesia:abort({badarg, Cs#cstruct.name, Storage}).opt_add(N, L) -> [N | lists:delete(N, L)].move_table(Tab, FromNode, ToNode) -> schema_transaction(fun() -> do_move_table(Tab, FromNode, ToNode) end).do_move_table(schema, _FromNode, _ToNode) -> mnesia:abort({bad_type, schema});do_move_table(Tab, FromNode, ToNode) when atom(FromNode), atom(ToNode) -> TidTs = get_tid_ts_and_lock(schema, write), insert_schema_ops(TidTs, make_move_table(Tab, FromNode, ToNode));do_move_table(Tab, FromNode, ToNode) -> mnesia:abort({badarg, Tab, FromNode, ToNode}).make_move_table(Tab, FromNode, ToNode) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), Ns = mnesia_lib:cs_to_nodes(Cs), verify(false, lists:member(ToNode, Ns), {already_exists, Tab, ToNode}), verify(true, lists:member(FromNode, val({Tab, where_to_write})), {not_active, Tab, FromNode}), verify(false, val({Tab,local_content}), {"Cannot move table with local content", Tab}), ensure_active(Cs), Running = val({current, db_nodes}), Storage = mnesia_lib:schema_cs_to_storage_type(FromNode, Cs), verify(true, lists:member(ToNode, Running), {not_active, schema, ToNode}), Cs2 = new_cs(Cs, ToNode, Storage, add), Cs3 = new_cs(Cs2, FromNode, Storage, del), verify_cstruct(Cs3), [{op, add_table_copy, Storage, ToNode, cs2list(Cs2)}, {op, sync_trans}, {op, del_table_copy, Storage, FromNode, cs2list(Cs3)}].%% end of functions to add and delete nodes to tables%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%change_table_copy_type(Tab, Node, ToS) -> schema_transaction(fun() -> do_change_table_copy_type(Tab, Node, ToS) end).do_change_table_copy_type(Tab, Node, ToS) when atom(Node) -> TidTs = get_tid_ts_and_lock(schema, write), get_tid_ts_and_lock(Tab, write), % ensure global sync %% get_tid_ts_and_lock(Tab, read), insert_schema_ops(TidTs, make_change_table_copy_type(Tab, Node, ToS));do_change_table_copy_type(Tab, Node, _ToS) -> mnesia:abort({badarg, Tab, Node}).make_change_table_copy_type(Tab, Node, unknown) -> make_del_table_copy(Tab, Node);make_change_table_copy_type(Tab, Node, ToS) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), FromS = mnesia_lib:storage_type_at_node(Node, Tab), case compare_storage_type(false, FromS, ToS) of {same, _} -> mnesia:abort({already_exists, Tab, Node, ToS}); {diff, _} -> ignore; incompatible -> ensure_active(Cs) end, Cs2 = new_cs(Cs, Node, FromS, del), Cs3 = new_cs(Cs2, Node, ToS, add), verify_cstruct(Cs3), if FromS == unknown -> make_add_table_copy(Tab, Node, ToS); true -> ignore end, [{op, change_table_copy_type, Node, FromS, ToS, cs2list(Cs3)}].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% change index functions ....%% Pos is allready added by 1 in both of these functions add_table_index(Tab, Pos) -> schema_transaction(fun() -> do_add_table_index(Tab, Pos) end).do_add_table_index(schema, _Attr) -> mnesia:abort({bad_type, schema});do_add_table_index(Tab, Attr) -> TidTs = get_tid_ts_and_lock(schema, write), get_tid_ts_and_lock(Tab, read), Pos = attr_tab_to_pos(Tab, Attr), insert_schema_ops(TidTs, make_add_table_index(Tab, Pos)).make_add_table_index(Tab, Pos) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), Ix = Cs#cstruct.index, verify(false, lists:member(Pos, Ix), {already_exists, Tab, Pos}), Ix2 = lists:sort([Pos | Ix]), Cs2 = Cs#cstruct{index = Ix2}, verify_cstruct(Cs2), [{op, add_index, Pos, cs2list(Cs2)}].del_table_index(Tab, Pos) -> schema_transaction(fun() -> do_del_table_index(Tab, Pos) end).do_del_table_index(schema, _Attr) -> mnesia:abort({bad_type, schema});do_del_table_index(Tab, Attr) -> TidTs = get_tid_ts_and_lock(schema, write), get_tid_ts_and_lock(Tab, read), Pos = attr_tab_to_pos(Tab, Attr), insert_schema_ops(TidTs, make_del_table_index(Tab, Pos)).make_del_table_index(Tab, Pos) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), Ix = Cs#cstruct.index, verify(true, lists:member(Pos, Ix), {no_exists, Tab, Pos}), Cs2 = Cs#cstruct{index = lists:delete(Pos, Ix)}, verify_cstruct(Cs2), [{op, del_index, Pos, cs2list(Cs2)}].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%add_snmp(Tab, Ustruct) -> schema_transaction(fun() -> do_add_snmp(Tab, Ustruct) end).do_add_snmp(schema, _Ustruct) -> mnesia:abort({bad_type, schema});do_add_snmp(Tab, Ustruct) -> TidTs = get_tid_ts_and_lock(schema, write), get_tid_ts_and_lock(Tab, read), insert_schema_ops(TidTs, make_add_snmp(Tab, Ustruct)).make_add_snmp(Tab, Ustruct) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), verify([], Cs#cstruct.snmp, {already_exists, Tab, snmp}), Error = {badarg, Tab, snmp, Ustruct}, verify(true, mnesia_snmp_hook:check_ustruct(Ustruct), Error), Cs2 = Cs#cstruct{snmp = Ustruct}, verify_cstruct(Cs2), [{op, add_snmp, Ustruct, cs2list(Cs2)}].del_snmp(Tab) -> schema_transaction(fun() -> do_del_snmp(Tab) end).do_del_snmp(schema) -> mnesia:abort({bad_type, schema});do_del_snmp(Tab) -> TidTs = get_tid_ts_and_lock(schema, write), get_tid_ts_and_lock(Tab, read), insert_schema_ops(TidTs, make_del_snmp(Tab)).make_del_snmp(Tab) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), Cs2 = Cs#cstruct{snmp = []}, verify_cstruct(Cs2), [{op, del_snmp, cs2list(Cs2)}].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% transform_table(Tab, Fun, NewAttrs, NewRecName) when function(Fun), list(NewAttrs), atom(NewRecName) -> schema_transaction(fun() -> do_transform_table(Tab, Fun, NewAttrs, NewRecName) end);transform_table(Tab, ignore, NewAttrs, NewRecName) when list(NewAttrs), atom(NewRecName) -> schema_transaction(fun() -> do_transform_table(Tab, ignore, NewAttrs, NewRecName) end);transform_table(Tab, Fun, NewAttrs, NewRecName) -> {aborted,{bad_type, Tab, Fun, NewAttrs, NewRecName}}.do_transform_table(schema, _Fun, _NewAttrs, _NewRecName) -> mnesia:abort({bad_type, schema});do_transform_table(Tab, Fun, NewAttrs, NewRecName) -> TidTs = get_tid_ts_and_lock(schema, write), get_tid_ts_and_lock(Tab, write), insert_schema_ops(TidTs, make_transform(Tab, Fun, NewAttrs, NewRecName)).make_transform(Tab, Fun, NewAttrs, NewRecName) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), ensure_writable(Tab), case mnesia_lib:val({Tab, index}) of [] -> Cs2 = Cs#cstruct{attributes = NewAttrs, record_name = NewRecName}, verify_cstruct(Cs2), [{op, transform, Fun, cs2list(Cs2)}]; PosList -> DelIdx = fun(Pos, Ncs) -> Ix = Ncs#cstruct.index, Ncs1 = Ncs#cstruct{index = lists:delete(Pos, Ix)}, Op = {op, del_index, Pos, cs2list(Ncs1)}, {Op, Ncs1} end, AddIdx = fun(Pos, Ncs) -> Ix = Ncs#cstruct.index, Ix2 = lists:sort([Pos | Ix]), Ncs1 = Ncs#cstruct{index = Ix2}, Op = {op, add_index, Pos, cs2list(Ncs1)}, {Op, Ncs1} end, {DelOps, Cs1} = lists:mapfoldl(DelIdx, Cs, PosList), Cs2 = Cs1#cstruct{attributes = NewAttrs, record_name = NewRecName}, {AddOps, Cs3} = lists:mapfoldl(AddIdx, Cs2, PosList), verify_cstruct(Cs3), lists:flatten([DelOps, {op, transform, Fun, cs2list(Cs2)}, AddOps]) end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% change_table_access_mode(Tab, Mode) -> schema_transaction(fun() -> do_change_table_access_mode(Tab, Mode) end).do_change_table_access_mode(Tab, Mode) -> {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, write), Store = Ts#tidstore.store, mnesia_locker:wlock_no_exist(Tid, Store, schema, val({schema, active_replicas})), mnesia_locker:wlock_no_exist(Tid, Store, Tab, val({Tab, active_replicas})), do_insert_schema_ops(Store, make_change_table_access_mode(Tab, Mode)).make_change_table_access_mode(Tab, Mode) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), OldMode = Cs#cstruct.access_mode, verify(false, OldMode == Mode, {already_exists, Tab, Mode}), Cs2 = Cs#cstruct{access_mode = Mode}, verify_cstruct(Cs2), [{op, change_table_access_mode, cs2list(Cs2), OldMode, Mode}].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%change_table_load_order(Tab, LoadOrder) -> schema_transaction(fun() -> do_change_table_load_order(Tab, LoadOrder) end).do_change_table_load_order(schema, _LoadOrder) -> mnesia:abort({bad_type, schema});do_change_table_load_order(Tab, LoadOrder) -> TidTs = get_tid_ts_and_lock(schema, write), get_tid_ts_and_lock(Tab, none), insert_schema_ops(TidTs, make_change_table_load_order(Tab, LoadOrder)).make_change_table_load_order(Tab, LoadOrder) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), OldLoadOrder = Cs#cstruct.load_order, Cs2 = Cs#cstruct{load_order = LoadOrder}, verify_cstruct(Cs2), [{op, change_table_load_order, cs2list(Cs2), OldLoadOrder, LoadOrder}].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%write_table_property(Tab, Prop) when tuple(Prop), size(Prop) >= 1 -> schema_transaction(fun() -> do_write_table_property(Tab, Prop) end);write_table_property(Tab, Prop) -> {aborted, {bad_type, Tab, Prop}}.do_write_table_property(Tab, Prop) -> TidTs = get_tid_ts_and_lock(schema, write), {_, _, Ts} = TidTs, Store = Ts#tidstore.store, case change_prop_in_existing_op(Tab, Prop, write_property, Store) of true -> dbg_out("change_prop_in_existing_op" "(~p,~p,write_property,Store) -> true~n", [Tab,Prop]), %% we have merged the table prop into the create_table op ok; false -> dbg_out("change_prop_in_existing_op" "(~p,~p,write_property,Store) -> false~n", [Tab,Prop]), %% this must be an existing table get_tid_ts_and_lock(Tab, none), insert_schema_ops(TidTs, make_write_table_properties(Tab, [Prop])) end.make_write_table_properties(Tab, Props) -> ensure_writable(schema), Cs = incr_version(val({Tab, cstruct})), ensure_active(Cs), make_write_table_properties(Tab, Props, Cs).make_write_table_properties(Tab, [Prop | Props], Cs) -> OldProps = Cs#cstruct.user_properties, PropKey = element(1, Prop), DelProps = lists:keydelete(PropKey, 1, OldProps), MergedProps = lists:merge(DelProps, [Prop]), Cs2 = Cs#cstruct{user_properties = MergedProps}, verify_cstruct(Cs2), [{op, write_property, cs2list(Cs2), Prop} | make_write_table_properties(Tab, Props, Cs2)];make_write_table_properties(_Tab, [], _Cs) -> [].change_prop_in_existing_op(Tab, Prop, How, Store) -> Ops = ets:match_object(Store, '_'), case update_existing_op(Ops, Tab, Prop, How, []) of {true, Ops1} -> ets:match_delete(Store, '_'), [ets:insert(Store, Op) || Op <- Ops1], true; false -> false end. update_existing_op([{op, Op, L = [{name,Tab}|_], _OldProp}|Ops], Tab, Prop, How, Acc) when Op == write_property; Op == delete_property -> %% Apparently, mnesia_dumper doesn't care about OldProp here -- just L, %% so we will throw away OldProp (not that it matters...) and insert Prop. %% as element 3. L1 = insert_prop(Prop, L, How), NewOp = {op, How, L1, Prop}, {true, lists:reverse(Acc) ++ [NewOp|Ops]};update_existing_op([Op = {op, create_table, L}|Ops], Tab, Prop, How, Acc) -> case lists:keysearch(name, 1, L) of {value, {_, Tab}} -> %% Tab is being created here -- insert Prop into L L1 = insert_prop(Prop, L, How), {true, lists:reverse(Acc) ++ [{op, create_table, L1}|Ops]}; _ -> update_existing_op(Ops, Tab, Prop, How, [Op|Acc]) end;update_existing_op([Op|Ops], Tab, Prop, How, Acc) -> update_existing_op(Ops, Tab, Prop, How, [Op|Acc]);update_existing_op([], _, _, _, _) -> false.do_read_table_property(Tab, Key) -> TidTs = get_tid_ts_and_lock(schema, read), {_, _, Ts} = TidTs, Store = Ts#tidstore.store, Props = ets:foldl( fun({op, create_table, [{name, T}|Opts]}, _Acc) when T==Tab -> find_props(Opts); ({op, Op, [{name,T}|Opts], _Prop}, _Acc) when T==Tab, Op==write_property; Op==delete_property -> find_props(Opts); ({op, delete_table, [{name,T}|_]}, _Acc) when T==Tab -> []; (_Other, Acc) -> Acc end, [], Store), case lists:keysearch(Key, 1, Props) of {value, Property} -> Property; false -> undefined end.%% perhaps a misnomer. How could also be delete_property... never mind.%% Returns the modified L.insert_prop(Prop, L, How) -> Prev = find_props(L), MergedProps = merge_with_previous(How, Prop, Prev), replace_props(L, MergedProps).find_props([{user_properties, P}|_]) -> P;find_props([_H|T]) -> find_props(T).%% we shouldn't reach []replace_props([{user_properties, _}|T], P) -> [{user_properties, P}|T];replace_props([H|T], P) -> [H|replace_props(T, P)].%% again, we shouldn't reach []
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?