【问题标题】:mongodb-erlang driver: mongo:do fails because of mongodb:next_requestid -> ets:update_counter fails with badargmongodb-erlang 驱动程序:mongo:do 由于 mongodb:next_requestid 而失败 -> ets:update_counter 因 badarg 而失败
【发布时间】:2012-02-18 18:54:19
【问题描述】:

我正在尝试创建一个使用 mongodb-erlang 作为驱动程序的 ejabberd 模块。

我这样做如下:

  1. ejabberd 启动我的模块,它使用 gen_server 启动一个子进程
  2. 我启动 mongodb 应用程序并设置一个 replset 池

    Replset = {<<"rs1">>, [{localhost, 27017}, {localhost, 27018}]},
    PoolSize = gen_mod:get_opt(poolsize, Opts, 2),
    Pool = resource_pool:new(mongo:rs_connect_factory(Replset), PoolSize),
    
  3. 为了访问池,我将池插入到 ets 表中

    try ets:new(mymodule_pool, [named_table, public]) of
            mymodule_pool -> ok
    catch
            _:_ -> alredy_existing
    end,
    ets:insert(mymodule_pool, {pool, Pool}),
    
  4. 当我注册的钩子被 ejabberd 调用时,我会从中获取池和连接

    Pool = element(2, lists:nth(1, ets:lookup(mod_log_chat_mongodb_pool, pool))),
    {ok, Conn} = resource_pool:get(Pool),
    
  5. 然后我尝试插入新文档。这就是它失败

    的地方
    mongo:do(unsafe, master, Conn, Db, fun() ->
            mongo:insert(Coll, Doc)
    end),
    

这是我得到的错误:

    {badarg,
     [{ets,
            update_counter,
            [mongodb_app,
             requestid_counter,
             1]},
            {mongodb_app,
             next_requestid,0},
            {mongo_connect,
             '-messages_binary/2-fun-0-',
             3},
            {lists,foldl,3},
            {mongo_connect,
             call,3},
            {mongo_query,
             find_one,2},
            {mongo_query,
             command,3},
            {mongo_replset,
             connect_member,2}]}

来自 erlang.log:

    =CRASH REPORT==== 25-Jan-2012::16:01:23 ===
      crasher:
        initial call: mymodule:init/1
        pid: <0.289.0>
        registered_name: mymodule_localhost
        exception exit: {badarg,[{ets,update_counter,
                              [mongodb_app,requestid_counter,1]},
                         {mongodb_app,next_requestid,0},
                         {mongo_connect,'-messages_binary/2-fun-0-',3},
                         {lists,foldl,3},
                         {mongo_connect,call,3},
                         {mongo_query,find_one,2},
                         {mongo_query,command,3},
                         {mongo_replset,connect_member,2}]}
          in function  gen_server:terminate/6
        ancestors: [ejabberd_sup,<0.36.0>]
        messages: []
        links: [<0.210.0>]
        dictionary: []
        trap_exit: false
        status: running
        heap_size: 1597
        stack_size: 24
        reductions: 1182
      neighbours:

我尝试了很多不同的方法,但我不知道为什么会失败。 在ets:update_counter manual中是badarg错误的原因描述如下:

  • 该表不是 set 或 ordered_set 类型,
  • 不存在具有正确键的对象,
  • 对象的元数有误,
  • 要更新的元素不是整数,
  • 要更新的元素也是键,或者,
  • Pos、Incr、Threshold 或 SetValue 中的任何一个都不是整数

mongodb_app相关代码如下:

    %@doc Create global vars which will be owned by this supervisor (and die with it)
    init ([]) ->
            ets:new (?MODULE, [named_table, public]),
            ets:insert (?MODULE, [
                    {oid_counter, 0}, 
                    {oid_machineprocid, oid_machineprocid()},
                    {requestid_counter, 0} ]), 
            {ok, {{one_for_one,3,10}, []}}.

    %% API functions

    -spec next_requestid () -> mongo_protocol:requestid(). % IO
    %@doc Fresh request id
    next_requestid() -> ets:update_counter (?MODULE, requestid_counter, 1). 

希望有人能帮帮我,我很无奈:(

非常感谢, 迈克尔

【问题讨论】:

    标签: mongodb erlang ejabberd


    【解决方案1】:

    我快速浏览了一下 mongodb_app,我怀疑是两件事之一。

    我怀疑的第一件事是 mongodb_app 实际上并没有运行。在调试或实时模式下运行它并确保 mongodb_app 在列表中。 应用程序:which_applications()。

    如果不是,请确保 application:start(mongodb_app) 在 你的模块启动。如果那在您的模块启动功能中,那么它 大概是时候检查一下应用的返回值了:start(mongodb_app)。

    我怀疑的第二件事是 ets 表有问题。调查表的状态 ets:信息(mongdb_app)。和 ets:tab2list(mongdb_app)。

    mongdb_app:init() 将该表声明为公共表,因此 不应该有任何拥有过程的问题。我不确定还有什么 建议除了调试 mongodb_app ets 表的状态和 从那里找到的任何线索重新回到您的代码中。

    【讨论】:

    • 嗨,Shaun,感谢您的评论,我将尝试检查 application:start 的返回值(是的,我确实启动了它,在我的 gen_server 的 init 函数中)。我测试后会尽快回复。
    • 我敢打赌 badarg 与不存在的 mongodb_app 表有关。要么是因为拥有进程已经死去,要么是因为它从一开始就没有启动。
    • 嗨,肖恩,好吧...谢谢。这有点尴尬。我只使用 ebin/*.beam 将构建的文件复制到 ejabberd ebin 目录中,但没有看到还有一个 .app 文件必须被复制。结果,应用程序无法启动,因为缺少应用程序文件并且 ets 表尚未复制。
    猜你喜欢
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 2018-02-16
    • 2016-05-23
    • 1970-01-01
    相关资源
    最近更新 更多