diff --git a/src/acl.erl b/src/acl.erl index 40ab682e5..0cdd7daa6 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -92,8 +92,6 @@ init([]) -> [{ram_copies, [node()]}, {local_content, true}, {attributes, record_info(fields, access)}]), - mnesia:add_table_copy(acl, node(), ram_copies), - mnesia:add_table_copy(access, node(), ram_copies), ejabberd_hooks:add(config_reloaded, ?MODULE, load_from_config, 20), load_from_config(), {ok, #state{}}. diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 579696302..214c38b21 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -46,7 +46,7 @@ start(normal, _Args) -> start_apps(), start_elixir_application(), ejabberd:check_app(ejabberd), - db_init(), + ejabberd_mnesia:start(), setup_if_elixir_conf_used(), ejabberd_config:start(), set_settings_from_config(), @@ -87,29 +87,6 @@ stop(_State) -> %%% Internal functions %%% -db_init() -> - ejabberd_config:env_binary_to_list(mnesia, dir), - MyNode = node(), - DbNodes = mnesia:system_info(db_nodes), - case lists:member(MyNode, DbNodes) of - true -> - ok; - false -> - ?CRITICAL_MSG("Node name mismatch: I'm [~s], " - "the database is owned by ~p", [MyNode, DbNodes]), - ?CRITICAL_MSG("Either set ERLANG_NODE in ejabberdctl.cfg " - "or change node name in Mnesia", []), - erlang:error(node_name_mismatch) - end, - case mnesia:system_info(extra_db_nodes) of - [] -> - mnesia:create_schema([node()]); - _ -> - ok - end, - ejabberd:start_app(mnesia, permanent), - mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity). - connect_nodes() -> Nodes = ejabberd_config:get_option( cluster_nodes, diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index d84a671d5..df0ce9123 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -297,7 +297,6 @@ init([]) -> {local_content, true}, {attributes, record_info(fields, ejabberd_commands)}, {type, bag}]), - mnesia:add_table_copy(ejabberd_commands, node(), ram_copies), register_commands(get_commands_spec()), ejabberd_access_permissions:register_permission_addon(?MODULE, fun permission_addon/0), {ok, #state{}}. diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 4b9e20f7a..bbef755a9 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -116,8 +116,7 @@ mnesia_init() -> ejabberd_mnesia:create(?MODULE, local_config, [{ram_copies, [node()]}, {local_content, true}, - {attributes, record_info(fields, local_config)}]), - mnesia:add_table_copy(local_config, node(), ram_copies). + {attributes, record_info(fields, local_config)}]). %% @doc Get the filename of the ejabberd configuration file. %% The filename can be specified with: erl -config "/path/to/ejabberd.yml". diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 00ce22274..c1b21d508 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -207,7 +207,6 @@ init([]) -> ejabberd_mnesia:create(?MODULE, iq_response, [{ram_copies, [node()]}, {attributes, record_info(fields, iq_response)}]), - mnesia:add_table_copy(iq_response, node(), ram_copies), {ok, #state{}}. handle_call(_Request, _From, State) -> diff --git a/src/ejabberd_mnesia.erl b/src/ejabberd_mnesia.erl index c0f25131a..1a1a62a51 100644 --- a/src/ejabberd_mnesia.erl +++ b/src/ejabberd_mnesia.erl @@ -30,21 +30,82 @@ -module(ejabberd_mnesia). -author('christophe.romain@process-one.net'). --export([create/3, reset/2, update/2]). + +-behaviour(gen_server). + +-export([start/0, create/3, reset/2, update/2]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). -define(STORAGE_TYPES, [disc_copies, disc_only_copies, ram_copies]). -define(NEED_RESET, [local_content, type]). -include("logger.hrl"). -create(Module, Name, TabDef) +-record(state, {tables = #{} :: map()}). + +start() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +create(Module, Name, TabDef) -> + gen_server:call(?MODULE, {create, Module, Name, TabDef}, + timer:seconds(60)). + +init([]) -> + ejabberd_config:env_binary_to_list(mnesia, dir), + MyNode = node(), + DbNodes = mnesia:system_info(db_nodes), + case lists:member(MyNode, DbNodes) of + true -> + case mnesia:system_info(extra_db_nodes) of + [] -> mnesia:create_schema([node()]); + _ -> ok + end, + ejabberd:start_app(mnesia, permanent), + ?DEBUG("Waiting for Mnesia tables synchronization...", []), + mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity), + {ok, #state{}}; + false -> + ?CRITICAL_MSG("Node name mismatch: I'm [~s], " + "the database is owned by ~p", [MyNode, DbNodes]), + ?CRITICAL_MSG("Either set ERLANG_NODE in ejabberdctl.cfg " + "or change node name in Mnesia", []), + {stop, node_name_mismatch} + end. + +handle_call({create, Module, Name, TabDef}, _From, State) -> + case maps:get(Name, State#state.tables, undefined) of + {TabDef, Result} -> + {reply, Result, State}; + _ -> + Result = do_create(Module, Name, TabDef), + Tables = maps:put(Name, {TabDef, Result}, State#state.tables), + {reply, Result, #state{tables = Tables}} + end; +handle_call(_Request, _From, State) -> + {noreply, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +do_create(Module, Name, TabDef) when is_atom(Module), is_atom(Name), is_list(TabDef) -> Path = os:getenv("EJABBERD_SCHEMA_PATH"), Schema = schema(Path, Module, Name, TabDef), {attributes, Attrs} = lists:keyfind(attributes, 1, Schema), case catch mnesia:table_info(Name, attributes) of {'EXIT', _} -> - mnesia_op(create_table, [Name, TabDef]); + create(Name, TabDef); Attrs -> case need_reset(Name, Schema) of true -> reset(Name, Schema); @@ -61,7 +122,7 @@ create(Module, Name, TabDef) reset(Name, TabDef) when is_atom(Name), is_list(TabDef) -> mnesia_op(delete_table, [Name]), - mnesia_op(create_table, [Name, TabDef]). + create(Name, TabDef). update(Name, TabDef) when is_atom(Name), is_list(TabDef) -> @@ -120,6 +181,25 @@ schema(Path, Module, Name, TabDef) -> TabDef end. +create(Name, TabDef) -> + case mnesia_op(create_table, [Name, TabDef]) of + {atomic, ok} -> + add_table_copy(Name); + Err -> + Err + end. + +%% The table MUST exist, otherwise the function would fail +add_table_copy(Name) -> + Type = mnesia:table_info(Name, storage_type), + Nodes = mnesia:table_info(Name, Type), + case lists:member(node(), Nodes) of + true -> + {atomic, ok}; + false -> + mnesia_op(add_table_copy, [Name, node(), Type]) + end. + merge(TabDef, CustomDef) -> {CustomKeys, _} = lists:unzip(CustomDef), CleanDef = lists:foldl( diff --git a/src/ejabberd_oauth_mnesia.erl b/src/ejabberd_oauth_mnesia.erl index 8a9997929..8908afd39 100644 --- a/src/ejabberd_oauth_mnesia.erl +++ b/src/ejabberd_oauth_mnesia.erl @@ -38,7 +38,6 @@ init() -> [{disc_copies, [node()]}, {attributes, record_info(fields, oauth_token)}]), - mnesia:add_table_copy(oauth_token, node(), disc_copies), ok. store(R) -> diff --git a/src/ejabberd_router_mnesia.erl b/src/ejabberd_router_mnesia.erl index d8664fee9..76336d0b0 100644 --- a/src/ejabberd_router_mnesia.erl +++ b/src/ejabberd_router_mnesia.erl @@ -145,7 +145,6 @@ init([]) -> [{ram_copies, [node()]}, {type, bag}, {attributes, record_info(fields, route)}]), - mnesia:add_table_copy(route, node(), ram_copies), mnesia:subscribe({table, route, simple}), lists:foreach( fun (Pid) -> erlang:monitor(process, Pid) end, diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index 39c119fbb..5d5acfcaa 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -120,7 +120,6 @@ init([]) -> {type, bag}, {attributes, record_info(fields, route_multicast)}]), - mnesia:add_table_copy(route_multicast, node(), ram_copies), mnesia:subscribe({table, route_multicast, simple}), lists:foreach( fun(Pid) -> diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 717e85ae4..61d3b021b 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -303,7 +303,6 @@ init([]) -> [{ram_copies, [node()]}, {type, bag}, {attributes, record_info(fields, s2s)}]), - mnesia:add_table_copy(s2s, node(), ram_copies), mnesia:subscribe(system), ejabberd_commands:register_commands(get_commands_spec()), ejabberd_mnesia:create(?MODULE, temporarily_blocked, diff --git a/src/ejabberd_sql_sup.erl b/src/ejabberd_sql_sup.erl index 995f90317..09aceafb4 100644 --- a/src/ejabberd_sql_sup.erl +++ b/src/ejabberd_sql_sup.erl @@ -53,7 +53,6 @@ start_link(Host) -> [{ram_copies, [node()]}, {type, bag}, {local_content, true}, {attributes, record_info(fields, sql_pool)}]), - mnesia:add_table_copy(sql_pool, node(), ram_copies), F = fun () -> mnesia:delete({sql_pool, Host}) end, mnesia:ets(F), supervisor:start_link({local, diff --git a/src/mod_bosh_mnesia.erl b/src/mod_bosh_mnesia.erl index 5954cbe49..d018077cb 100644 --- a/src/mod_bosh_mnesia.erl +++ b/src/mod_bosh_mnesia.erl @@ -168,5 +168,4 @@ setup_database() -> end, ejabberd_mnesia:create(?MODULE, bosh, [{ram_copies, [node()]}, {local_content, true}, - {attributes, record_info(fields, bosh)}]), - mnesia:add_table_copy(bosh, node(), ram_copies). + {attributes, record_info(fields, bosh)}]). diff --git a/src/mod_caps_mnesia.erl b/src/mod_caps_mnesia.erl index 02ea9aaf0..30fbf766f 100644 --- a/src/mod_caps_mnesia.erl +++ b/src/mod_caps_mnesia.erl @@ -49,9 +49,7 @@ init(_Host, _Opts) -> {local_content, true}, {attributes, record_info(fields, caps_features)}]), - update_table(), - mnesia:add_table_copy(caps_features, node(), - disc_only_copies). + update_table(). caps_read(_LServer, Node) -> case mnesia:dirty_read({caps_features, Node}) of diff --git a/src/mod_carboncopy_mnesia.erl b/src/mod_carboncopy_mnesia.erl index 8b248a2de..589686c71 100644 --- a/src/mod_carboncopy_mnesia.erl +++ b/src/mod_carboncopy_mnesia.erl @@ -49,8 +49,7 @@ init(_Host, _Opts) -> ejabberd_mnesia:create(?MODULE, carboncopy, [{ram_copies, [node()]}, {attributes, record_info(fields, carboncopy)}, - {type, bag}]), - mnesia:add_table_copy(carboncopy, node(), ram_copies). + {type, bag}]). enable(LUser, LServer, LResource, NS) -> mnesia:dirty_write( diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl index 6a9adf4b5..8cbdfe6bd 100644 --- a/src/mod_muc_mnesia.erl +++ b/src/mod_muc_mnesia.erl @@ -318,7 +318,6 @@ init([Host, Opts]) -> [{ram_copies, [node()]}, {type, ordered_set}, {attributes, record_info(fields, muc_online_room)}]), - mnesia:add_table_copy(muc_online_room, node(), ram_copies), catch ets:new(muc_online_users, [bag, named_table, public, {keypos, 2}]), clean_table_from_bad_node(node(), MyHost), mnesia:subscribe(system); diff --git a/src/mod_proxy65_mnesia.erl b/src/mod_proxy65_mnesia.erl index 2763fab6a..f2a7cc8d5 100644 --- a/src/mod_proxy65_mnesia.erl +++ b/src/mod_proxy65_mnesia.erl @@ -104,7 +104,6 @@ init([]) -> ejabberd_mnesia:create(?MODULE, bytestream, [{ram_copies, [node()]}, {attributes, record_info(fields, bytestream)}]), - mnesia:add_table_copy(bytestream, node(), ram_copies), {ok, #state{}}. handle_call({activate_stream, SHA1, Initiator, MaxConnections}, _From, State) -> diff --git a/src/mod_register.erl b/src/mod_register.erl index d14d49358..e15165f77 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -57,8 +57,6 @@ start(Host, Opts) -> ejabberd_mnesia:create(?MODULE, mod_register_ip, [{ram_copies, [node()]}, {local_content, true}, {attributes, [key, value]}]), - mnesia:add_table_copy(mod_register_ip, node(), - ram_copies), ok. stop(Host) -> diff --git a/src/shaper.erl b/src/shaper.erl index cc1923f86..b4db64586 100644 --- a/src/shaper.erl +++ b/src/shaper.erl @@ -62,7 +62,6 @@ init([]) -> [{ram_copies, [node()]}, {local_content, true}, {attributes, record_info(fields, shaper)}]), - mnesia:add_table_copy(shaper, node(), ram_copies), ejabberd_hooks:add(config_reloaded, ?MODULE, load_from_config, 20), load_from_config(), {ok, #state{}}.