[erlang-bugs] Funny behaviour of dirty_next in mnesia?

John Hughes john.hughes@REDACTED
Tue May 17 18:57:38 CEST 2011


QuickCheck turned up another case of odd behaviour at Klarna.

The test runs mnesia on two nodes, creates a table on the OTHER node, then adds and deletes a record. After this the record is indeed not IN the table, but dirty_next finds its key anyway! Surely it shouldn't?

Here's the test:

test() ->
    Slave = start_mnesia_with_slave(),
    {atomic,ok} = mnesia:create_table(rec,[{type,set},
        {disc_only_copies,[Slave]}]),
    ok          = mnesia:dirty_write({rec,4,1}),
    %% The next command MUST be done in a transaction, otherwise dirty_next works
    {atomic,ok} = mnesia:transaction(fun()->mnesia:delete_object({rec,4,1}) end),
    %% Here's the problem: dirty_next returns 4, but this key is not in the table!
    4           = mnesia:dirty_next(rec,0),
    []          = mnesia:dirty_read(rec,4).

I'm starting mnesia and the slave node like this:

start_mnesia_with_slave() ->
    {ok,Dir} = file:get_cwd(),
    ok = error_logger:tty(false),
    mnesia:stop(),
    ok = error_logger:tty(true),
    delete_file("mnesia"),
    delete_file("slave"),
    ok = file:make_dir("mnesia"),
    ok = file:make_dir("slave"),
    Slave = slave(),
    ok = application:set_env(mnesia,dir,Dir++"/mnesia"),
    ok = rpc:call(Slave,application,set_env,[mnesia,dir,Dir++"/slave"]),
    ok = mnesia:create_schema([node(),Slave]),
    ok = mnesia:start(),
    ok = rpc:call(Slave,mnesia,start,[]),
    Slave.

slave() ->
    case slave:start_link(net_adm:localhost(),"slave") of
 {ok,Slave} ->
     Slave;
 {error,{already_running,Slave}} ->
     Slave
    end.

I also have code to delete a file or directory, easy on Linux, darn difficult on Windows. You don't need this really, just run the test in an empty directory.

delete_file(Name) ->
    case filelib:is_dir(Name) of
 true ->
     [delete_file(Name++"/"++X) || X <- list_dir(Name)],
     file:del_dir(Name),
     delete_file(Name);
 {error,eaccess} ->
     delete_file(Name);
 {error,enoent} ->
     io:format("Could not find ~p\n",[Name]),
     ok;
 false ->
     case file:delete(Name) of
  {error,enoent} ->
      ok;
  {error,eacces} ->
      io:format("Could not access ~p\n",[Name]),
      delete_file(Name);
  ok ->
      delete_file(Name)
     end
    end.

list_dir(Name) ->
    case file:list_dir(Name) of
 {ok,Files} ->
     Files;
 {error,eacces} ->
     io:format("Could not list directory ~p\n",[Name]),
     list_dir(Name);
 {error,enoent} ->
     io:format("Could not find directory ~p\n",[Name]),
     []     
    end.

John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-bugs/attachments/20110517/08f44f60/attachment.htm>


More information about the erlang-bugs mailing list