0

我正在编写一个 ejabberd 模块,在以下两种情况下需要在停止时执行不同的清理操作:

  • 当前同一模块正在其他集群节点上运行。
  • 这是我的模块的最后一个仍在运行的实例。

我考虑以下解决方案:

is_there_running_instances() ->
    {Results, _} = rpc:multicall(nodes(), ?MODULE, ejabberd_loaded_modules, []),
    lists:member(?MODULE, lists:append(Results)).

ejabberd_loaded_modules() -> ???.

但不知道如何获取已加载模块的列表。我该怎么做?还是我的问题有更好的解决方案?

4

3 回答 3

1

code:all_loaded/0返回一个类型的元组列表,{ModuleName,ModuleAbsolutePath}其中 ModuleName 是一个原子, ModuleAbsolutePath 是一个字符串。您可以使用路径信息过滤此列表,然后将其解压缩以仅获取它包含的模块。加载所有模块后,我使用 eunit 库对其进行测试:

26> Filter = fun(Path,Lib) -> string:str(Path,Lib) > 0 end.                         
#Fun<erl_eval.12.80484245>
27> [Mod || {Mod,Path} <- code:all_loaded() , is_list(Path), Filter(Path,"eunit")].
[eunit,eunit_proc,eunit_test,eunit_data,eunit_surefire,
 eunit_serial,eunit_tests,eunit_autoexport,eunit_tty,
 eunit_server,eunit_striptests,eunit_lib,eunit_listener]
于 2013-11-05T12:48:35.270 回答
1

试试看

gen_mod:loaded_modules(Host)

是你需要的

于 2013-11-05T14:21:29.460 回答
0

首先使用 code:all_loaded/0 获取所有加载的模块列表,然后使用“mod_”前缀过滤结果。

ejabberd_loaded_modules() -> 
    AllLoaded = code:all_loaded(),
    Filter = fun({Module, _}) ->
        case re:run(atom_to_list(Module), "mod_") of
            {match,[{0,4}]} -> true;
            _ -> false
        end
    end,
    lists:filter(Filter, AllLoaded).

您还可以执行行为检查。它应该是 gen_mod。

is_gen_mod(Module) ->
    BehavioursList = 
    case lists:getkey(1, behaviour, Module:module_info(attributes)) of
        {behaviour, L} -> L;
        false -> []
    end,
    lists:member(gen_mod, BehavioursList).

在这种情况下, ejabberd_loaded_modules/0 函数将是:

ejabberd_loaded_modules() ->
    ...
    ModPreffixed = lists:filter(Filter, AllLoaded),
    lists:filter(fun is_gen_mod/1, ModPreffixed).
于 2013-11-05T14:54:20.077 回答