Michael Weibel
Michael Weibel

Reputation: 2962

mongodb-erlang driver: mongo:do fails because of mongodb:next_requestid -> ets:update_counter fails with badarg

I'm trying to create an ejabberd module which uses mongodb-erlang as the driver.

I'm doing this as follows:

  1. ejabberd starts my module, which starts a child process with gen_server
  2. I start mongodb application and setup a replset pool

    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. to get access to the pool, I insert the pool into an ets table

    try ets:new(mymodule_pool, [named_table, public]) of
            mymodule_pool -> ok
    catch
            _:_ -> alredy_existing
    end,
    ets:insert(mymodule_pool, {pool, Pool}),
    
  4. when my registered hook gets called by ejabberd, I fetch the pool and a connection from it

    Pool = element(2, lists:nth(1, ets:lookup(mod_log_chat_mongodb_pool, pool))),
    {ok, Conn} = resource_pool:get(Pool),
    
  5. then I try to insert the new doc. This is where it fails

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

This is the error I get:

    {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}]}

And from 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:

I tried a lot of different things but I don't have a clue why this fails. In ets:update_counter manual is the reason for badarg errors described as follows:

The relevant code of mongodb_app is as follows:

    %@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). 

I hope someone can help me for this, I'm helpless :(

Thank you very much, Michael

Upvotes: 0

Views: 786

Answers (1)

Shaun Kruger
Shaun Kruger

Reputation: 500

I took a quick look at mongodb_app and I suspect one of two things.

The first thing I suspect is that mongodb_app isn't actually running. Run this in debug or live mode and make sure mongodb_app is in the list. application:which_applications().

If it isn't then make sure that application:start(mongodb_app) is in your module startup. If that is in your module start function then it is probably time to check the return value of the application:start(mongodb_app).

The second thing I suspect is that there is a problem with the ets table. Investigate the status of the table with ets:info(mongdb_app). and ets:tab2list(mongdb_app).

mongdb_app:init() declares the table as a public table so there shouldn't be any owning process issues. I'm not sure what else to suggest other than debugging the state of the mongodb_app ets table and working your way back into your code from any clues you find there.

Upvotes: 1

Related Questions