]> granicus.if.org Git - ejabberd/commitdiff
Speedup Mnesia tables initialization
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Fri, 21 Apr 2017 09:27:15 +0000 (12:27 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Fri, 21 Apr 2017 09:27:15 +0000 (12:27 +0300)
18 files changed:
src/acl.erl
src/ejabberd_app.erl
src/ejabberd_commands.erl
src/ejabberd_config.erl
src/ejabberd_local.erl
src/ejabberd_mnesia.erl
src/ejabberd_oauth_mnesia.erl
src/ejabberd_router_mnesia.erl
src/ejabberd_router_multicast.erl
src/ejabberd_s2s.erl
src/ejabberd_sql_sup.erl
src/mod_bosh_mnesia.erl
src/mod_caps_mnesia.erl
src/mod_carboncopy_mnesia.erl
src/mod_muc_mnesia.erl
src/mod_proxy65_mnesia.erl
src/mod_register.erl
src/shaper.erl

index 40ab682e5dea98a38d83d1a56211ef65b8486237..0cdd7daa65a379c19b67aa99fec4a082cdc4d3e1 100644 (file)
@@ -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{}}.
index 579696302141e55fff39f6750441eb9291261777..214c38b2108bc92b96d45a7c79fef10d0c5a82d2 100644 (file)
@@ -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,
index d84a671d520c1c813937fd57eb11f60193c20a54..df0ce91233240eb6f346c7304311afc9ece0de18 100644 (file)
@@ -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{}}.
index 4b9e20f7a29c13de2d552ba4ac3fa19619ceae40..bbef755a91252c4389bed6a79ed418af01d5f5a1 100644 (file)
@@ -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".
index 00ce222743bf79fcb600e3c59c1462304fb8e962..c1b21d50862d069d7d7331b6dfde558d0d7919a5 100644 (file)
@@ -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) ->
index c0f25131a87f8ae3607228a88ea1e8276fe07045..1a1a62a51fea5021f4fb429b708d4b9a3275ba5e 100644 (file)
 
 -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(
index 8a99979294bc622e5b2bc76a621b46038e46793f..8908afd396274f945d551bb85a6c73fb8a0d5d9a 100644 (file)
@@ -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) ->
index d8664fee9def629c42bdfb557b69578070729872..76336d0b0235f10ac893b1e610f328cc88c3e8a6 100644 (file)
@@ -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,
index 39c119fbb531064b06722eb5d073af33f04ee205..5d5acfcaa7a50da839d35b335532e2db01328c8e 100644 (file)
@@ -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) ->
index 717e85ae46d3f558ec90f0c2783f62778cbacbf9..61d3b021b965295700518bf7bc1f91b419267d5e 100644 (file)
@@ -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,
index 995f90317051d35e1be7e59451bfc41151688e58..09aceafb4bc033d5774aed417c4b460f0e81732d 100644 (file)
@@ -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,
index 5954cbe4914bc87a95226ae2d40bc2b24e44e640..d018077cb6e43dfd9c14f1df44cf21229c07c4a7 100644 (file)
@@ -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)}]).
index 02ea9aaf02a540b38dc33b727dd508478484eb90..30fbf766f7cd0e98c1f79c88711481fef5a0f160 100644 (file)
@@ -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
index 8b248a2de0e8a1dbe522c954e8ac775d50602f20..589686c7177504b146a04b28d45436e2d04a2c7e 100644 (file)
@@ -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(
index 6a9adf4b5d47f7010536e5b3d87e6c1e355e694a..8cbdfe6bda7cb925c240bada5e7c5efe19a25a74 100644 (file)
@@ -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);
index 2763fab6aa734a67bbab5cc8729084dcff8dbcfa..f2a7cc8d5f6b8ee7c0f1007ebd307229dbbf56f8 100644 (file)
@@ -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) ->
index d14d49358ff9ea6241ac1f3c3f385eaaefcc58f9..e15165f7792c0c1bdf24e9561adb5adbc79b391f 100644 (file)
@@ -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) ->
index cc1923f86c02a113b33bbc72887e86bbf4a611b1..b4db645867228a1c8772988264e2d8fa37d640f3 100644 (file)
@@ -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{}}.