]> granicus.if.org Git - ejabberd/commitdiff
Improve detection of databases supported by modules (#1092)
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 27 Apr 2016 14:10:50 +0000 (17:10 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 27 Apr 2016 14:10:50 +0000 (17:10 +0300)
20 files changed:
src/ejabberd_auth.erl
src/ejabberd_config.erl
src/ejabberd_riak_sup.erl
src/ejabberd_sm.erl
src/gen_mod.erl
src/mod_announce.erl
src/mod_caps.erl
src/mod_carboncopy.erl
src/mod_irc.erl
src/mod_last.erl
src/mod_mam.erl
src/mod_muc.erl
src/mod_offline.erl
src/mod_privacy.erl
src/mod_private.erl
src/mod_pubsub.erl
src/mod_roster.erl
src/mod_shared_roster.erl
src/mod_vcard.erl
src/mod_vcard_xupdate.erl

index 927abdac2799d8ecd9aa213c536d4482c9f04d5b..6b7f537c0bb8487bdf23cd2a29b722bb16486eef 100644 (file)
@@ -428,7 +428,7 @@ auth_modules() ->
 %% Return the list of authenticated modules for a given host
 auth_modules(Server) ->
     LServer = jid:nameprep(Server),
-    Default = gen_mod:default_db(LServer),
+    Default = ejabberd_config:default_db(LServer, ?MODULE),
     Methods = ejabberd_config:get_option(
                 {auth_method, LServer}, opt_type(auth_method), [Default]),
     [jlib:binary_to_atom(<<"ejabberd_auth_",
@@ -448,15 +448,9 @@ import(Server, riak, Passwd) ->
 import(_, _, _) ->
     pass.
 
--spec v_auth_method(atom()) -> atom().
-
-v_auth_method(odbc) -> sql;
-v_auth_method(internal) -> mnesia;
-v_auth_method(A) when is_atom(A) -> A.
-
 opt_type(auth_method) ->
     fun (V) when is_list(V) ->
-           lists:map(fun v_auth_method/1, V);
-       (V) -> [v_auth_method(V)]
+           lists:map(fun(M) -> ejabberd_config:v_db(?MODULE, M) end, V);
+       (V) -> [ejabberd_config:v_db(?MODULE, V)]
     end;
 opt_type(_) -> [auth_method].
index 7fccbc744a3414a72c2350d03b09f08792c6b582..87f465e1395097c693ea7a6e628ebe75c1aa2b5c 100644 (file)
@@ -34,8 +34,8 @@
          get_vh_by_auth_method/1, is_file_readable/1,
          get_version/0, get_myhosts/0, get_mylang/0,
          prepare_opt_val/4, convert_table_to_binary/5,
-         transform_options/1, collect_options/1,
-         convert_to_yaml/1, convert_to_yaml/2,
+         transform_options/1, collect_options/1, default_db/2,
+         convert_to_yaml/1, convert_to_yaml/2, v_db/2,
          env_binary_to_list/2, opt_type/1, may_hide_data/1]).
 
 -export([start/2]).
@@ -674,7 +674,16 @@ rename_option(Option) ->
 
 change_val(auth_method, Val) ->
     prepare_opt_val(auth_method, Val,
-                   ejabberd_auth:opt_type(auth_method), [mnesia]);
+                   fun(V) ->
+                           L = if is_list(V) -> V;
+                                  true -> [V]
+                               end,
+                           lists:map(
+                             fun(odbc) -> sql;
+                                (internal) -> mnesia;
+                                (A) when is_atom(A) -> A
+                             end, L)
+                   end, [mnesia]);
 change_val(_Opt, Val) ->
     Val.
 
@@ -806,9 +815,57 @@ get_option(Opt, F, Default) ->
             end
     end.
 
+init_module_db_table(Modules) ->
+    catch ets:new(module_db, [named_table, public, bag]),
+    %% Dirty hack for mod_pubsub
+    ets:insert(module_db, {mod_pubsub, mnesia}),
+    ets:insert(module_db, {mod_pubsub, sql}),
+    lists:foreach(
+      fun(M) ->
+             case re:split(atom_to_list(M), "_", [{return, list}]) of
+                 [_] ->
+                     ok;
+                 Parts ->
+                     [Suffix|T] = lists:reverse(Parts),
+                     BareMod = string:join(lists:reverse(T), "_"),
+                     ets:insert(module_db, {list_to_atom(BareMod),
+                                            list_to_atom(Suffix)})
+             end
+      end, Modules).
+
+-spec v_db(module(), atom()) -> atom().
+
+v_db(Mod, internal) -> v_db(Mod, mnesia);
+v_db(Mod, odbc) -> v_db(Mod, sql);
+v_db(Mod, Type) ->
+    case ets:match_object(module_db, {Mod, Type}) of
+       [_|_] -> Type;
+       [] -> erlang:error(badarg)
+    end.
+
+-spec default_db(binary(), module()) -> atom().
+
+default_db(Host, Module) ->
+    case ejabberd_config:get_option(
+          {default_db, Host}, fun(T) when is_atom(T) -> T end) of
+       undefined ->
+           mnesia;
+       DBType ->
+           try
+               v_db(Module, DBType)
+           catch error:badarg ->
+                   ?WARNING_MSG("Module '~s' doesn't support database '~s' "
+                                "defined in option 'default_db', using "
+                                "'mnesia' as fallback", [Module, DBType]),
+                   mnesia
+           end
+    end.
+
 get_modules_with_options() ->
     {ok, Mods} = application:get_key(ejabberd, modules),
     ExtMods = [Name || {Name, _Details} <- ext_mod:installed()],
+    AllMods = [?MODULE|ExtMods++Mods],
+    init_module_db_table(AllMods),
     lists:foldl(
       fun(Mod, D) ->
              case catch Mod:opt_type('') of
@@ -820,7 +877,7 @@ get_modules_with_options() ->
                  {'EXIT', {undef, _}} ->
                      D
              end
-      end, dict:new(), [?MODULE|ExtMods++Mods]).
+      end, dict:new(), AllMods).
 
 validate_opts(#state{opts = Opts} = State) ->
     ModOpts = get_modules_with_options(),
index af811441bb1de9f6db1124672b39641b19f7d156..ad65ecf80e7d834c62e9d5143d847e68d15cdef2 100644 (file)
@@ -70,8 +70,8 @@ is_riak_configured(Host) ->
                {modules, Host},
                fun(L) when is_list(L) -> L end, []),
     ModuleWithRiakDBConfigured = lists:any(
-                                  fun({_Module, Opts}) ->
-                                          gen_mod:db_type(Host, Opts) == riak
+                                  fun({Module, Opts}) ->
+                                          gen_mod:db_type(Host, Opts, Module) == riak
                                   end, Modules),
     ServerConfigured or PortConfigured
        or AuthConfigured or ModuleWithRiakDBConfigured.
index 9a93e6d97b3e6fc983ddca6e6ab44ffc499f01a6..20b0658d5d5c0be2a4d2cfae25df9632eb6ee34c 100644 (file)
@@ -733,13 +733,10 @@ force_update_presence({LUser, LServer}) ->
 -spec get_sm_backend(binary()) -> module().
 
 get_sm_backend(Host) ->
-    DBType = ejabberd_config:get_option({sm_db_type, Host},
-                                       fun(mnesia) -> mnesia;
-                                          (internal) -> mnesia;
-                                          (odbc) -> sql;
-                                          (sql) -> sql;
-                                          (redis) -> redis
-                                       end, mnesia),
+    DBType = ejabberd_config:get_option(
+              {sm_db_type, Host},
+              fun(T) -> ejabberd_config:v_db(?MODULE, T) end,
+              mnesia),
     list_to_atom("ejabberd_sm_" ++ atom_to_list(DBType)).
 
 -spec get_sm_backends() -> [module()].
@@ -812,11 +809,5 @@ kick_user(User, Server) ->
 make_sid() ->
     {p1_time_compat:unique_timestamp(), self()}.
 
-opt_type(sm_db_type) ->
-    fun (mnesia) -> mnesia;
-       (internal) -> mnesia;
-       (sql) -> sql;
-       (odbc) -> sql;
-       (redis) -> redis
-    end;
+opt_type(sm_db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 opt_type(_) -> [sm_db_type].
index 26e662dc68d15d6532b812c6941b50ea2532b5a8..efbfc087f09f7acda72741fdf9c358948dea99d4 100644 (file)
 
 -export([start/0, start_module/2, start_module/3,
         stop_module/2, stop_module_keep_config/2, get_opt/3,
-        get_opt/4, get_opt_host/3, db_type/1, db_type/2,
+        get_opt/4, get_opt_host/3, db_type/2, db_type/3,
         get_module_opt/4, get_module_opt/5, get_module_opt_host/3,
         loaded_modules/1, loaded_modules_with_opts/1,
         get_hosts/2, get_module_proc/2, is_loaded/2,
         start_modules/0, start_modules/1, stop_modules/0, stop_modules/1,
-        default_db/1, v_db/1, opt_type/1, db_mod/2, db_mod/3]).
+        opt_type/1, db_mod/2, db_mod/3]).
 
 %%-export([behaviour_info/1]).
 
@@ -295,44 +295,46 @@ validate_opts(Module, Opts) ->
              false
       end, Opts).
 
--spec v_db(db_type() | internal) -> db_type().
-
-v_db(odbc) -> sql;
-v_db(sql) -> sql;
-v_db(internal) -> mnesia;
-v_db(mnesia) -> mnesia;
-v_db(riak) -> riak.
-
--spec db_type(opts()) -> db_type().
-
-db_type(Opts) ->
-    db_type(global, Opts).
-
--spec db_type(binary() | global, atom() | opts()) -> db_type().
+-spec db_type(binary() | global, module()) -> db_type();
+            (opts(), module()) -> db_type().
 
+db_type(Opts, Module) when is_list(Opts) ->
+    db_type(global, Opts, Module);
 db_type(Host, Module) when is_atom(Module) ->
-    get_module_opt(Host, Module, db_type, fun v_db/1, default_db(Host));
-db_type(Host, Opts) when is_list(Opts) ->
-    get_opt(db_type, Opts, fun v_db/1, default_db(Host)).
-
--spec default_db(binary() | global) -> db_type().
+    case Module:mod_opt_type(db_type) of
+       F when is_function(F) ->
+           case get_module_opt(Host, Module, db_type, F) of
+               undefined -> ejabberd_config:default_db(Host, Module);
+               Type -> Type
+           end;
+       _ ->
+           undefined
+    end.
 
-default_db(Host) ->
-    ejabberd_config:get_option({default_db, Host}, fun v_db/1, mnesia).
+-spec db_type(binary(), opts(), module()) -> db_type().
+
+db_type(Host, Opts, Module) ->
+    case Module:mod_opt_type(db_type) of
+       F when is_function(F) ->
+           case get_opt(db_type, Opts, F) of
+               undefined -> ejabberd_config:default_db(Host, Module);
+               Type -> Type
+           end;
+       _ ->
+           undefined
+    end.
 
 -spec db_mod(binary() | global | db_type(), module()) -> module().
 
-db_mod(odbc, Module) -> list_to_atom(atom_to_list(Module) ++ "_sql");
-db_mod(sql, Module) -> list_to_atom(atom_to_list(Module) ++ "_sql");
-db_mod(mnesia, Module) -> list_to_atom(atom_to_list(Module) ++ "_mnesia");
-db_mod(riak, Module) -> list_to_atom(atom_to_list(Module) ++ "_riak");
+db_mod(Type, Module) when is_atom(Type) ->
+    list_to_atom(atom_to_list(Module) ++ "_" ++ atom_to_list(Type));
 db_mod(Host, Module) when is_binary(Host) orelse Host == global ->
     db_mod(db_type(Host, Module), Module).
 
 -spec db_mod(binary() | global, opts(), module()) -> module().
 
 db_mod(Host, Opts, Module) when is_list(Opts) ->
-    db_mod(db_type(Host, Opts), Module).
+    db_mod(db_type(Host, Opts, Module), Module).
 
 -spec loaded_modules(binary()) -> [atom()].
 
@@ -380,6 +382,6 @@ get_module_proc(Host, Base) ->
 is_loaded(Host, Module) ->
     ets:member(ejabberd_modules, {Module, Host}).
 
-opt_type(default_db) -> fun v_db/1;
+opt_type(default_db) -> fun(T) when is_atom(T) -> T end;
 opt_type(modules) -> fun (L) when is_list(L) -> L end;
 opt_type(_) -> [default_db, modules].
index d7251c50b432d3bc3a91cccce85991ec0bda1c5c..9a9e665f5171fd3d91ea2a1d664f7610b2a04bd3 100644 (file)
@@ -921,5 +921,5 @@ import(LServer, DBType, LA) ->
 
 mod_opt_type(access) ->
     fun (A) when is_atom(A) -> A end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(_) -> [access, db_type].
index 3d5c360a8ad56458905c0f9e86ac526b9f9e90b3..966a9baa65e989068e2e21bb27a3ee88428c004e 100644 (file)
@@ -651,6 +651,6 @@ mod_opt_type(cache_life_time) ->
     fun (I) when is_integer(I), I > 0 -> I end;
 mod_opt_type(cache_size) ->
     fun (I) when is_integer(I), I > 0 -> I end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(_) ->
     [cache_life_time, cache_size, db_type].
index ebf1d0b0fc2d8c8f7cfa69838fadf54af49fce04..bb20bd2f908068d4c1d22b080f0fcd3db8175e5d 100644 (file)
@@ -279,8 +279,5 @@ list(User, Server) ->
     Mod:list(User, Server).
 
 mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
-mod_opt_type(db_type) ->
-    fun(internal) -> mnesia;
-       (mnesia) -> mnesia
-    end;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(_) -> [db_type, iqdisc].
index e0c658deab2a0420f2790e11e0438fc67726b67c..f6487a1a9946cecf51733bb81b7a9dfedd011fdc 100644 (file)
@@ -1253,7 +1253,7 @@ import(LServer, DBType, Data) ->
 
 mod_opt_type(access) ->
     fun (A) when is_atom(A) -> A end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(default_encoding) ->
     fun iolist_to_binary/1;
 mod_opt_type(host) -> fun iolist_to_binary/1;
index 1af1847b3b68cdb8262eb511055eae262160d6e8..c39681f69385bdeca15123de66e1a9d9922e96e6 100644 (file)
@@ -244,7 +244,7 @@ transform_options({node_start, {_, _, _} = Now}, Opts) ->
 transform_options(Opt, Opts) ->
     [Opt|Opts].
 
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
 mod_opt_type(_) -> [db_type, iqdisc].
 
index f84519a080bbb4bc72533f0a9dac94c0d1390dd6..d5ee9bf868daf46cc7063e8e2387db34aa2b9967 100644 (file)
@@ -1017,12 +1017,7 @@ mod_opt_type(cache_life_time) ->
     fun (I) when is_integer(I), I > 0 -> I end;
 mod_opt_type(cache_size) ->
     fun (I) when is_integer(I), I > 0 -> I end;
-mod_opt_type(db_type) ->
-    fun(sql) -> sql;
-       (odbc) -> sql;
-       (internal) -> mnesia;
-       (mnesia) -> mnesia
-    end;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(default) ->
     fun (always) -> always;
        (never) -> never;
index 6aa1863189cd3a2305a81d67a9818a7118eb5f77..3d098e0d5fe6656becb80e44d896b31e986ee522 100644 (file)
@@ -932,7 +932,7 @@ mod_opt_type(access_create) ->
     fun (A) when is_atom(A) -> A end;
 mod_opt_type(access_persistent) ->
     fun (A) when is_atom(A) -> A end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(default_room_options) ->
     fun (L) when is_list(L) -> L end;
 mod_opt_type(history_size) ->
index 356d89a67f3f6627f8d011bea72fc38ad8b42c8a..4d8aba76204f8c3548fef27347e547d092bb8d4a 100644 (file)
@@ -867,7 +867,7 @@ import(LServer, DBType, Data) ->
 
 mod_opt_type(access_max_user_messages) ->
     fun (A) -> A end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(store_empty_body) ->
     fun (V) when is_boolean(V) -> V;
         (unless_chat_state) -> unless_chat_state
index 413dcb52a1ac5f50755d1e7dcd0f119d3232978f..ad13c27cde7743f445d006906898c53f6bf9e2bb 100644 (file)
@@ -593,6 +593,6 @@ import(LServer, DBType, Data) ->
     Mod = gen_mod:db_mod(DBType, ?MODULE),
     Mod:import(LServer, Data).
 
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
 mod_opt_type(_) -> [db_type, iqdisc].
index 029789e633a0540e86384fd15729ab5e344a8f80..38e42ca4c540c6f74da3443f160fb40ae02442a5 100644 (file)
@@ -173,6 +173,6 @@ import(LServer, DBType, PD) ->
     Mod = gen_mod:db_mod(DBType, ?MODULE),
     Mod:import(LServer, PD).
 
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
 mod_opt_type(_) -> [db_type, iqdisc].
index a86155af893757c0f217ae975fa3e3c324da1ecb..a801fa984b17ea59597dd3887d037090cf1f8672 100644 (file)
@@ -4470,7 +4470,7 @@ purge_offline(Host, LJID, Node) ->
 
 mod_opt_type(access_createnode) ->
     fun (A) when is_atom(A) -> A end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(host) -> fun iolist_to_binary/1;
 mod_opt_type(ignore_pep_from_offline) ->
     fun (A) when is_boolean(A) -> A end;
index 16354dd8f25d35c181b78d552c8fc5c74646df3a..b3a627f7c5d7993bb00a9bd06a90683fc4b6789d 100644 (file)
@@ -1236,7 +1236,7 @@ import(LServer, DBType, R) ->
 
 mod_opt_type(access) ->
     fun (A) when is_atom(A) -> A end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
 mod_opt_type(managers) ->
     fun (B) when is_list(B) -> B end;
index 6670cf77bb50404de2d5a25999de00adeb62d195..76a619c9bba4bfb6684d2a0d9788fb85a79287e3 100644 (file)
@@ -1120,5 +1120,5 @@ import(LServer, DBType, Data) ->
     Mod = gen_mod:db_mod(DBType, ?MODULE),
     Mod:import(LServer, Data).
 
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(_) -> [db_type].
index e5f5d9e3ca3f42d0270cba45a6072b5622ea05d3..5e042528b34f8c96d7524b6a4422380219d1e291 100644 (file)
@@ -596,7 +596,7 @@ import(LServer, DBType, VCard) ->
 
 mod_opt_type(allow_return_all) ->
     fun (B) when is_boolean(B) -> B end;
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(host) -> fun iolist_to_binary/1;
 mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
 mod_opt_type(matches) ->
index 198312c364128b6fed90295c3ed4b78ea2e6b8df..041b0b64c6a36ce72332ba5296d0d373727d6e7c 100644 (file)
@@ -133,5 +133,5 @@ import(LServer, DBType, LA) ->
     Mod = gen_mod:db_mod(DBType, ?MODULE),
     Mod:import(LServer, LA).
 
-mod_opt_type(db_type) -> fun gen_mod:v_db/1;
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
 mod_opt_type(_) -> [db_type].