diff options
Diffstat (limited to 'lib/mnesia/src/mnesia_controller.erl')
-rw-r--r-- | lib/mnesia/src/mnesia_controller.erl | 73 |
1 files changed, 68 insertions, 5 deletions
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl index 0254769758..1d3bd55b48 100644 --- a/lib/mnesia/src/mnesia_controller.erl +++ b/lib/mnesia/src/mnesia_controller.erl @@ -57,7 +57,8 @@ release_schema_commit_lock/0, create_table/1, get_disc_copy/1, - get_cstructs/0, + get_remote_cstructs/0, % new function + get_cstructs/0, % old function sync_and_block_table_whereabouts/4, sync_del_table_copy_whereabouts/2, block_table/1, @@ -72,6 +73,7 @@ add_active_replica/4, update/1, change_table_access_mode/1, + change_table_majority/1, del_active_replica/2, wait_for_tables/2, get_network_copy/2, @@ -277,9 +279,51 @@ rec_tabs([], _, _, Init) -> unlink(Init), ok. -get_cstructs() -> +%% New function that does exactly what get_cstructs() used to do. +%% When this function is called, we know that the calling node knows +%% how to convert cstructs on the receiving end (should they differ). +get_remote_cstructs() -> call(get_cstructs). +%% Old function kept for backwards compatibility; converts cstructs before sending. +get_cstructs() -> + {cstructs, Cstructs, Running} = call(get_cstructs), + Node = node(group_leader()), + {cstructs, normalize_cstructs(Cstructs, Node), Running}. + +normalize_cstructs(Cstructs, Node) -> + %% backward-compatibility hack; normalize before returning + case rpc:call(Node, mnesia_lib, val, [{schema,cstruct}]) of + {badrpc, _} -> + %% assume it's not a schema merge + Cstructs; + #cstruct{} -> + %% same format + Cstructs; + Cstruct -> + %% some other format + RemoteFields = [F || {F,_} <- rpc:call(Node, mnesia_schema, cs2list, [Cstruct])], + [convert_cs(Cs, RemoteFields) || Cs <- Cstructs] + end. + +convert_cs(Cs, Fields) -> + MyFields = record_info(fields, cstruct), + convert(tl(tuple_to_list(Cs)), MyFields, Fields, []). + +convert([H|T], [F|FsL], [F|FsR], Acc) -> + convert(T, FsL, FsR, [H|Acc]); +convert([H|T], [Fl|FsL] = L, [Fr|FsR] = R, Acc) -> + case {lists:member(Fl, FsR), lists:member(Fr, FsL)} of + {true, false} -> + convert(T, L, FsR, [H|Acc]); + {false, true} -> + %% Field Fl doesn't exist on receiver side; skip. + convert(T, FsL, R, Acc) + end; +convert([], _, _, Acc) -> + list_to_tuple([cstruct|lists:reverse(Acc)]). + + update(Fun) -> call({update,Fun}). @@ -690,7 +734,8 @@ handle_call({update_where_to_write, [add, Tab, AddNode], _From}, _Dummy, State) case lists:member(AddNode, Current) and (State#state.schema_is_merged == true) of true -> - mnesia_lib:add_lsort({Tab, where_to_write}, AddNode); + mnesia_lib:add_lsort({Tab, where_to_write}, AddNode), + update_where_to_wlock(Tab); false -> ignore end, @@ -1690,6 +1735,8 @@ add_active_replica(Tab, Node, Storage, AccessMode) -> set(Var, mark_blocked_tab(Blocked, Del)), mnesia_lib:del({Tab, where_to_write}, Node) end, + + update_where_to_wlock(Tab), add({Tab, active_replicas}, Node). del_active_replica(Tab, Node) -> @@ -1699,7 +1746,8 @@ del_active_replica(Tab, Node) -> New = lists:sort(Del), set(Var, mark_blocked_tab(Blocked, New)), % where_to_commit mnesia_lib:del({Tab, active_replicas}, Node), - mnesia_lib:del({Tab, where_to_write}, Node). + mnesia_lib:del({Tab, where_to_write}, Node), + update_where_to_wlock(Tab). change_table_access_mode(Cs) -> W = fun() -> @@ -1708,7 +1756,22 @@ change_table_access_mode(Cs) -> val({Tab, active_replicas})) end, update(W). - + +change_table_majority(Cs) -> + W = fun() -> + Tab = Cs#cstruct.name, + set({Tab, majority}, Cs#cstruct.majority), + update_where_to_wlock(Tab) + end, + update(W). + +update_where_to_wlock(Tab) -> + WNodes = val({Tab, where_to_write}), + Majority = case catch val({Tab, majority}) of + true -> true; + _ -> false + end, + set({Tab, where_to_wlock}, {WNodes, Majority}). %% node To now has tab loaded, but this must be undone %% This code is rpc:call'ed from the tab_copier process |