diff options
Diffstat (limited to 'src/ejabberd_admin.erl')
-rw-r--r-- | src/ejabberd_admin.erl | 340 |
1 files changed, 261 insertions, 79 deletions
diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index ae2fac3e1..3e02e6bd0 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -5,7 +5,7 @@ %%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2016 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -26,13 +26,17 @@ -module(ejabberd_admin). -author('mickael.remond@process-one.net'). --export([start/0, stop/0, +-behaviour(gen_server). + +-export([start_link/0, %% Server status/0, reopen_log/0, rotate_log/0, set_loglevel/1, stop_kindly/2, send_service_message_all_mucs/2, registered_vhosts/0, reload_config/0, + dump_config/1, + convert_to_yaml/2, %% Cluster join_cluster/1, leave_cluster/1, list_cluster/0, %% Erlang @@ -48,23 +52,50 @@ set_master/1, backup_mnesia/1, restore_mnesia/1, dump_mnesia/1, dump_table/2, load_mnesia/1, + mnesia_info/0, mnesia_table_info/1, install_fallback_mnesia/1, dump_to_textfile/1, dump_to_textfile/2, mnesia_change_nodename/4, restore/1, % Still used by some modules + clear_cache/0, + gc/0, get_commands_spec/0 ]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). --include("ejabberd.hrl"). -include("logger.hrl"). -include("ejabberd_commands.hrl"). -start() -> - ejabberd_commands:register_commands(get_commands_spec()). +-record(state, {}). + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +init([]) -> + process_flag(trap_exit, true), + ejabberd_commands:register_commands(get_commands_spec()), + {ok, #state{}}. + +handle_call(Request, From, State) -> + ?WARNING_MSG("Unexpected call from ~p: ~p", [From, Request]), + {noreply, State}. + +handle_cast(Msg, State) -> + ?WARNING_MSG("Unexpected cast: ~p", [Msg]), + {noreply, State}. -stop() -> +handle_info(Info, State) -> + ?WARNING_MSG("Unexpected info: ~p", [Info]), + {noreply, State}. + +terminate(_Reason, _State) -> ejabberd_commands:unregister_commands(get_commands_spec()). +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + %%% %%% ejabberd commands %%% @@ -76,6 +107,9 @@ get_commands_spec() -> #ejabberd_commands{name = status, tags = [server], desc = "Get status of the ejabberd server", module = ?MODULE, function = status, + result_desc = "Result tuple", + result_example = {ok, <<"The node ejabberd@localhost is started with status: started" + "ejabberd X.X is running in that node">>}, args = [], result = {res, restuple}}, #ejabberd_commands{name = stop, tags = [server], desc = "Stop ejabberd gracefully", @@ -97,34 +131,40 @@ get_commands_spec() -> #ejabberd_commands{name = stop_kindly, tags = [server], desc = "Inform users and rooms, wait, and stop the server", longdesc = "Provide the delay in seconds, and the " - "announcement quoted, for example: \n" - "ejabberdctl stop_kindly 60 " - "\\\"The server will stop in one minute.\\\"", + "announcement quoted, for example: \n" + "ejabberdctl stop_kindly 60 " + "\\\"The server will stop in one minute.\\\"", module = ?MODULE, function = stop_kindly, + args_desc = ["Seconds to wait", "Announcement to send, with quotes"], + args_example = [60, <<"Server will stop now.">>], args = [{delay, integer}, {announcement, string}], result = {res, rescode}}, #ejabberd_commands{name = get_loglevel, tags = [logs, server], desc = "Get the current loglevel", module = ejabberd_logger, function = get, + result_desc = "Tuple with the log level number, its keyword and description", + result_example = warning, args = [], - result = {leveltuple, {tuple, [{levelnumber, integer}, - {levelatom, atom}, - {leveldesc, string} - ]}}}, + result = {levelatom, atom}}, #ejabberd_commands{name = set_loglevel, tags = [logs, server], - desc = "Set the loglevel (0 to 5)", + desc = "Set the loglevel", module = ?MODULE, function = set_loglevel, - args = [{loglevel, integer}], - result = {logger, atom}}, + args_desc = ["Desired logging level: none | emergency | alert | critical " + "| error | warning | notice | info | debug"], + args_example = [debug], + args = [{loglevel, string}], + result = {res, rescode}}, #ejabberd_commands{name = update_list, tags = [server], desc = "List modified modules that can be updated", module = ?MODULE, function = update_list, args = [], + result_example = ["mod_configure", "mod_vcard"], result = {modules, {list, {module, string}}}}, #ejabberd_commands{name = update, tags = [server], desc = "Update the given module, or use the keyword: all", module = ?MODULE, function = update, + args_example = ["mod_vcard"], args = [{module, string}], result = {res, restuple}}, @@ -132,25 +172,36 @@ get_commands_spec() -> desc = "Register a user", policy = admin, module = ?MODULE, function = register, + args_desc = ["Username", "Local vhost served by ejabberd", "Password"], + args_example = [<<"bob">>, <<"example.com">>, <<"SomEPass44">>], args = [{user, binary}, {host, binary}, {password, binary}], result = {res, restuple}}, #ejabberd_commands{name = unregister, tags = [accounts], desc = "Unregister a user", + policy = admin, module = ?MODULE, function = unregister, + args_desc = ["Username", "Local vhost served by ejabberd"], + args_example = [<<"bob">>, <<"example.com">>], args = [{user, binary}, {host, binary}], result = {res, restuple}}, #ejabberd_commands{name = registered_users, tags = [accounts], desc = "List all registered users in HOST", module = ?MODULE, function = registered_users, + args_desc = ["Local vhost"], + args_example = [<<"example.com">>], + result_desc = "List of registered accounts usernames", + result_example = [<<"user1">>, <<"user2">>], args = [{host, binary}], result = {users, {list, {username, string}}}}, - #ejabberd_commands{name = registered_vhosts, tags = [server], + #ejabberd_commands{name = registered_vhosts, tags = [server], desc = "List all registered vhosts in SERVER", module = ?MODULE, function = registered_vhosts, + result_desc = "List of available vhosts", + result_example = [<<"example.com">>, <<"anon.example.com">>], args = [], result = {vhosts, {list, {vhost, string}}}}, - #ejabberd_commands{name = reload_config, tags = [server], - desc = "Reload config file in memory (only affects ACL and Access)", + #ejabberd_commands{name = reload_config, tags = [server, config], + desc = "Reload config file in memory", module = ?MODULE, function = reload_config, args = [], result = {res, rescode}}, @@ -158,61 +209,95 @@ get_commands_spec() -> #ejabberd_commands{name = join_cluster, tags = [cluster], desc = "Join this node into the cluster handled by Node", module = ?MODULE, function = join_cluster, + args_desc = ["Nodename of the node to join"], + args_example = [<<"ejabberd1@machine7">>], args = [{node, binary}], result = {res, rescode}}, #ejabberd_commands{name = leave_cluster, tags = [cluster], - desc = "Remove node handled by Node from the cluster", + desc = "Remove and shutdown Node from the running cluster", + longdesc = "This command can be run from any running node of the cluster, " + "even the node to be removed.", module = ?MODULE, function = leave_cluster, + args_desc = ["Nodename of the node to kick from the cluster"], + args_example = [<<"ejabberd1@machine8">>], args = [{node, binary}], result = {res, rescode}}, + #ejabberd_commands{name = list_cluster, tags = [cluster], desc = "List nodes that are part of the cluster handled by Node", module = ?MODULE, function = list_cluster, + result_example = [ejabberd1@machine7, ejabberd1@machine8], args = [], result = {nodes, {list, {node, atom}}}}, #ejabberd_commands{name = import_file, tags = [mnesia], desc = "Import user data from jabberd14 spool file", module = ?MODULE, function = import_file, + args_desc = ["Full path to the jabberd14 spool file"], + args_example = ["/var/lib/ejabberd/jabberd14.spool"], args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = import_dir, tags = [mnesia], desc = "Import users data from jabberd14 spool dir", module = ?MODULE, function = import_dir, + args_desc = ["Full path to the jabberd14 spool directory"], + args_example = ["/var/lib/ejabberd/jabberd14/"], args = [{file, string}], result = {res, restuple}}, - #ejabberd_commands{name = import_piefxis, tags = [mnesia], desc = "Import users data from a PIEFXIS file (XEP-0227)", module = ejabberd_piefxis, function = import_file, + args_desc = ["Full path to the PIEFXIS file"], + args_example = ["/var/lib/ejabberd/example.com.xml"], args = [{file, string}], result = {res, rescode}}, #ejabberd_commands{name = export_piefxis, tags = [mnesia], desc = "Export data of all users in the server to PIEFXIS files (XEP-0227)", module = ejabberd_piefxis, function = export_server, + args_desc = ["Full path to a directory"], + args_example = ["/var/lib/ejabberd/"], args = [{dir, string}], result = {res, rescode}}, #ejabberd_commands{name = export_piefxis_host, tags = [mnesia], desc = "Export data of users in a host to PIEFXIS files (XEP-0227)", module = ejabberd_piefxis, function = export_host, + args_desc = ["Full path to a directory", "Vhost to export"], + args_example = ["/var/lib/ejabberd/", "example.com"], args = [{dir, string}, {host, string}], result = {res, rescode}}, #ejabberd_commands{name = delete_mnesia, tags = [mnesia, sql], - desc = "Export all tables as SQL queries to a file", + desc = "Delete elements in Mnesia database for a given vhost", module = ejd2sql, function = delete, + args_desc = ["Vhost which content will be deleted in Mnesia database"], + args_example = ["example.com"], args = [{host, string}], result = {res, rescode}}, #ejabberd_commands{name = convert_to_scram, tags = [sql], desc = "Convert the passwords in 'users' ODBC table to SCRAM", module = ejabberd_auth_sql, function = convert_to_scram, + args_desc = ["Vhost which users' passwords will be scrammed"], + args_example = ["example.com"], args = [{host, binary}], result = {res, rescode}}, - #ejabberd_commands{name = import_prosody, tags = [mnesia, sql, riak], + #ejabberd_commands{name = import_prosody, tags = [mnesia, sql], desc = "Import data from Prosody", + longdesc = "Note: this method requires ejabberd compiled with optional tools support " + "and package must provide optional luerl dependency.", module = prosody2ejabberd, function = from_dir, + args_desc = ["Full path to the Prosody data directory"], + args_example = ["/var/lib/prosody/datadump/"], args = [{dir, string}], result = {res, rescode}}, #ejabberd_commands{name = convert_to_yaml, tags = [config], desc = "Convert the input file from Erlang to YAML format", - module = ejabberd_config, function = convert_to_yaml, + module = ?MODULE, function = convert_to_yaml, + args_desc = ["Full path to the original configuration file", "And full path to final file"], + args_example = ["/etc/ejabberd/ejabberd.cfg", "/etc/ejabberd/ejabberd.yml"], args = [{in, string}, {out, string}], result = {res, rescode}}, + #ejabberd_commands{name = dump_config, tags = [config], + desc = "Dump configuration in YAML format as seen by ejabberd", + module = ?MODULE, function = dump_config, + args_desc = ["Full path to output file"], + args_example = ["/tmp/ejabberd.yml"], + args = [{out, string}], + result = {res, rescode}}, #ejabberd_commands{name = delete_expired_messages, tags = [purge], desc = "Delete expired offline messages from database", @@ -221,11 +306,16 @@ get_commands_spec() -> #ejabberd_commands{name = delete_old_messages, tags = [purge], desc = "Delete offline messages older than DAYS", module = ?MODULE, function = delete_old_messages, + args_desc = ["Number of days"], + args_example = [31], args = [{days, integer}], result = {res, rescode}}, #ejabberd_commands{name = export2sql, tags = [mnesia], - desc = "Export virtual host information from Mnesia tables to SQL files", + desc = "Export virtual host information from Mnesia tables to SQL file", + longdesc = "Configure the modules to use SQL, then call this command.", module = ejd2sql, function = export, + args_desc = ["Vhost", "Full path to the destination SQL file"], + args_example = ["example.com", "/var/lib/ejabberd/example.com.sql"], args = [{host, string}, {file, string}], result = {res, rescode}}, #ejabberd_commands{name = set_master, tags = [mnesia], @@ -233,37 +323,73 @@ get_commands_spec() -> longdesc = "If you provide as nodename \"self\", this " "node will be set as its own master.", module = ?MODULE, function = set_master, + args_desc = ["Name of the erlang node that will be considered master of this node"], + args_example = ["ejabberd@machine7"], args = [{nodename, string}], result = {res, restuple}}, #ejabberd_commands{name = mnesia_change_nodename, tags = [mnesia], desc = "Change the erlang node name in a backup file", module = ?MODULE, function = mnesia_change_nodename, + args_desc = ["Name of the old erlang node", "Name of the new node", + "Path to old backup file", "Path to the new backup file"], + args_example = ["ejabberd@machine1", "ejabberd@machine2", + "/var/lib/ejabberd/old.backup", "/var/lib/ejabberd/new.backup"], args = [{oldnodename, string}, {newnodename, string}, {oldbackup, string}, {newbackup, string}], result = {res, restuple}}, #ejabberd_commands{name = backup, tags = [mnesia], desc = "Store the database to backup file", module = ?MODULE, function = backup_mnesia, + args_desc = ["Full path for the destination backup file"], + args_example = ["/var/lib/ejabberd/database.backup"], args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = restore, tags = [mnesia], desc = "Restore the database from backup file", module = ?MODULE, function = restore_mnesia, + args_desc = ["Full path to the backup file"], + args_example = ["/var/lib/ejabberd/database.backup"], args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = dump, tags = [mnesia], - desc = "Dump the database to text file", + desc = "Dump the database to a text file", module = ?MODULE, function = dump_mnesia, + args_desc = ["Full path for the text file"], + args_example = ["/var/lib/ejabberd/database.txt"], args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = dump_table, tags = [mnesia], - desc = "Dump a table to text file", + desc = "Dump a table to a text file", module = ?MODULE, function = dump_table, + args_desc = ["Full path for the text file", "Table name"], + args_example = ["/var/lib/ejabberd/table-muc-registered.txt", "muc_registered"], args = [{file, string}, {table, string}], result = {res, restuple}}, #ejabberd_commands{name = load, tags = [mnesia], - desc = "Restore the database from text file", + desc = "Restore the database from a text file", module = ?MODULE, function = load_mnesia, + args_desc = ["Full path to the text file"], + args_example = ["/var/lib/ejabberd/database.txt"], args = [{file, string}], result = {res, restuple}}, + #ejabberd_commands{name = mnesia_info, tags = [mnesia], + desc = "Dump info on global Mnesia state", + module = ?MODULE, function = mnesia_info, + args = [], result = {res, string}}, + #ejabberd_commands{name = mnesia_table_info, tags = [mnesia], + desc = "Dump info on Mnesia table state", + module = ?MODULE, function = mnesia_table_info, + args_desc = ["Mnesia table name"], + args_example = ["roster"], + args = [{table, string}], result = {res, string}}, #ejabberd_commands{name = install_fallback, tags = [mnesia], desc = "Install the database from a fallback file", module = ?MODULE, function = install_fallback_mnesia, - args = [{file, string}], result = {res, restuple}} + args_desc = ["Full path to the fallback file"], + args_example = ["/var/lib/ejabberd/database.fallback"], + args = [{file, string}], result = {res, restuple}}, + #ejabberd_commands{name = clear_cache, tags = [server], + desc = "Clear database cache on all nodes", + module = ?MODULE, function = clear_cache, + args = [], result = {res, rescode}}, + #ejabberd_commands{name = gc, tags = [server], + desc = "Force full garbage collection", + module = ?MODULE, function = gc, + args = [], result = {res, rescode}} ]. @@ -280,37 +406,43 @@ status() -> false -> {ejabberd_not_running, "ejabberd is not running in that node."}; {value, {_, _, Version}} -> - {ok, io_lib:format("ejabberd ~s is running in that node", [Version])} + {ok, io_lib:format("ejabberd ~ts is running in that node", [Version])} end, {Is_running, String1 ++ String2}. reopen_log() -> - ejabberd_hooks:run(reopen_log_hook, []), - ejabberd_logger:reopen_log(). + ejabberd_hooks:run(reopen_log_hook, []). rotate_log() -> - ejabberd_hooks:run(rotate_log_hook, []), - ejabberd_logger:rotate_log(). + ejabberd_hooks:run(rotate_log_hook, []). set_loglevel(LogLevel) -> - {module, Module} = ejabberd_logger:set(LogLevel), - Module. - + try binary_to_existing_atom(iolist_to_binary(LogLevel), latin1) of + Level -> + case lists:member(Level, ejabberd_logger:loglevels()) of + true -> + ejabberd_logger:set(Level); + false -> + {error, "Invalid log level"} + end + catch _:_ -> + {error, "Invalid log level"} + end. %%% %%% Stop Kindly %%% stop_kindly(DelaySeconds, AnnouncementTextString) -> - Subject = list_to_binary(io_lib:format("Server stop in ~p seconds!", [DelaySeconds])), - WaitingDesc = list_to_binary(io_lib:format("Waiting ~p seconds", [DelaySeconds])), + Subject = (str:format("Server stop in ~p seconds!", [DelaySeconds])), + WaitingDesc = (str:format("Waiting ~p seconds", [DelaySeconds])), AnnouncementText = list_to_binary(AnnouncementTextString), Steps = [ {"Stopping ejabberd port listeners", ejabberd_listener, stop_listeners, []}, {"Sending announcement to connected users", mod_announce, send_announcement_to_all, - [?MYNAME, Subject, AnnouncementText]}, + [ejabberd_config:get_myname(), Subject, AnnouncementText]}, {"Sending service message to MUC rooms", ejabberd_admin, send_service_message_all_mucs, [Subject, AnnouncementText]}, @@ -318,7 +450,7 @@ stop_kindly(DelaySeconds, AnnouncementTextString) -> {"Stopping ejabberd", application, stop, [ejabberd]}, {"Stopping Mnesia", mnesia, stop, []}, {"Stopping Erlang node", init, stop, []} - ], + ], NumberLast = length(Steps), TimestampStart = calendar:datetime_to_gregorian_seconds({date(), time()}), lists:foldl( @@ -326,7 +458,7 @@ stop_kindly(DelaySeconds, AnnouncementTextString) -> SecondsDiff = calendar:datetime_to_gregorian_seconds({date(), time()}) - TimestampStart, - io:format("[~p/~p ~ps] ~s... ", + io:format("[~p/~p ~ps] ~ts... ", [NumberThis, NumberLast, SecondsDiff, Desc]), Result = (catch apply(Mod, Func, Args)), io:format("~p~n", [Result]), @@ -337,15 +469,16 @@ stop_kindly(DelaySeconds, AnnouncementTextString) -> ok. send_service_message_all_mucs(Subject, AnnouncementText) -> - Message = list_to_binary( - io_lib:format("~s~n~s", [Subject, AnnouncementText])), + Message = str:format("~ts~n~ts", [Subject, AnnouncementText]), lists:foreach( fun(ServerHost) -> - MUCHost = gen_mod:get_module_opt_host( - ServerHost, mod_muc, <<"conference.@HOST@">>), - mod_muc:broadcast_service_message(MUCHost, Message) + MUCHosts = gen_mod:get_module_opt_hosts(ServerHost, mod_muc), + lists:foreach( + fun(MUCHost) -> + mod_muc:broadcast_service_message(ServerHost, MUCHost, Message) + end, MUCHosts) end, - ?MYHOSTS). + ejabberd_option:hosts()). %%% %%% ejabberd_update @@ -367,8 +500,8 @@ update_module(ModuleNameBin) when is_binary(ModuleNameBin) -> update_module(ModuleNameString) -> ModuleName = list_to_atom(ModuleNameString), case ejabberd_update:update([ModuleName]) of - {ok, _Res} -> {ok, []}; - {error, Reason} -> {error, Reason} + {ok, _Res} -> {ok, []}; + {error, Reason} -> {error, Reason} end. %%% @@ -376,34 +509,69 @@ update_module(ModuleNameString) -> %%% register(User, Host, Password) -> - case ejabberd_auth:try_register(User, Host, Password) of - {atomic, ok} -> - {ok, io_lib:format("User ~s@~s successfully registered", [User, Host])}; - {atomic, exists} -> - Msg = io_lib:format("User ~s@~s already registered", [User, Host]), - {error, conflict, 10090, Msg}; - {error, Reason} -> - String = io_lib:format("Can't register user ~s@~s at node ~p: ~p", - [User, Host, node(), Reason]), - {error, cannot_register, 10001, String} + case is_my_host(Host) of + true -> + case ejabberd_auth:try_register(User, Host, Password) of + ok -> + {ok, io_lib:format("User ~ts@~ts successfully registered", [User, Host])}; + {error, exists} -> + Msg = io_lib:format("User ~ts@~ts already registered", [User, Host]), + {error, conflict, 10090, Msg}; + {error, Reason} -> + String = io_lib:format("Can't register user ~ts@~ts at node ~p: ~ts", + [User, Host, node(), + mod_register:format_error(Reason)]), + {error, cannot_register, 10001, String} + end; + false -> + {error, cannot_register, 10001, "Unknown virtual host"} end. unregister(User, Host) -> - ejabberd_auth:remove_user(User, Host), - {ok, ""}. + case is_my_host(Host) of + true -> + ejabberd_auth:remove_user(User, Host), + {ok, ""}; + false -> + {error, "Unknown virtual host"} + end. registered_users(Host) -> - Users = ejabberd_auth:get_vh_registered_users(Host), - SUsers = lists:sort(Users), - lists:map(fun({U, _S}) -> U end, SUsers). + case is_my_host(Host) of + true -> + Users = ejabberd_auth:get_users(Host), + SUsers = lists:sort(Users), + lists:map(fun({U, _S}) -> U end, SUsers); + false -> + {error, "Unknown virtual host"} + end. registered_vhosts() -> - ?MYHOSTS. + ejabberd_option:hosts(). reload_config() -> - ejabberd_config:reload_file(), - acl:start(), - shaper:start(). + case ejabberd_config:reload() of + ok -> {ok, ""}; + Err -> + Reason = ejabberd_config:format_error(Err), + {error, Reason} + end. + +dump_config(Path) -> + case ejabberd_config:dump(Path) of + ok -> {ok, ""}; + Err -> + Reason = ejabberd_config:format_error(Err), + {error, Reason} + end. + +convert_to_yaml(In, Out) -> + case ejabberd_config:convert_to_yaml(In, Out) of + ok -> {ok, ""}; + Err -> + Reason = ejabberd_config:format_error(Err), + {error, Reason} + end. %%% %%% Cluster management @@ -442,7 +610,6 @@ import_dir(Path) -> {cannot_import_dir, String} end. - %%% %%% Purge DB %%% @@ -451,13 +618,13 @@ delete_expired_messages() -> lists:foreach( fun(Host) -> {atomic, ok} = mod_offline:remove_expired_messages(Host) - end, ?MYHOSTS). + end, ejabberd_option:hosts()). delete_old_messages(Days) -> lists:foreach( fun(Host) -> {atomic, _} = mod_offline:remove_old_messages(Days, Host) - end, ?MYHOSTS). + end, ejabberd_option:hosts()). %%% %%% Mnesia management @@ -491,10 +658,6 @@ restore_mnesia(Path) -> case ejabberd_admin:restore(Path) of {atomic, _} -> {ok, ""}; - {error, Reason} -> - String = io_lib:format("Can't restore backup from ~p at node ~p: ~p", - [filename:absname(Path), node(), Reason]), - {cannot_restore, String}; {aborted,{no_exists,Table}} -> String = io_lib:format("Can't restore backup from ~p at node ~p: Table ~p does not exist.", [filename:absname(Path), node(), Table]), @@ -517,20 +680,19 @@ restore(Path) -> %% Obsolete tables or tables created by module who are no longer used are not %% restored and are ignored. keep_tables() -> - lists:flatten([acl, passwd, config, local_config, + lists:flatten([acl, passwd, config, keep_modules_tables()]). %% Returns the list of modules tables in use, according to the list of actually %% loaded modules keep_modules_tables() -> lists:map(fun(Module) -> module_tables(Module) end, - gen_mod:loaded_modules(?MYNAME)). + gen_mod:loaded_modules(ejabberd_config:get_myname())). %% TODO: This mapping should probably be moved to a callback function in each %% module. %% Mapping between modules and their tables module_tables(mod_announce) -> [motd, motd_users]; -module_tables(mod_irc) -> [irc_custom]; module_tables(mod_last) -> [last_activity]; module_tables(mod_muc) -> [muc_room, muc_registered]; module_tables(mod_offline) -> [offline_msg]; @@ -610,6 +772,13 @@ load_mnesia(Path) -> {cannot_load, String} end. +mnesia_info() -> + lists:flatten(io_lib:format("~p", [mnesia:system_info(all)])). + +mnesia_table_info(Table) -> + ATable = list_to_atom(Table), + lists:flatten(io_lib:format("~p", [mnesia:table_info(ATable, all)])). + install_fallback_mnesia(Path) -> case mnesia:install_fallback(Path) of ok -> @@ -665,3 +834,16 @@ mnesia_change_nodename(FromString, ToString, Source, Target) -> {[Other], Acc} end, mnesia:traverse_backup(Source, Target, Convert, switched). + +clear_cache() -> + Nodes = ejabberd_cluster:get_nodes(), + lists:foreach(fun(T) -> ets_cache:clear(T, Nodes) end, ets_cache:all()). + +gc() -> + lists:foreach(fun erlang:garbage_collect/1, processes()). + +-spec is_my_host(binary()) -> boolean(). +is_my_host(Host) -> + try ejabberd_router:is_my_host(Host) + catch _:{invalid_domain, _} -> false + end. |