[erlang-bugs] Funny behaviour of dirty_next in mnesia?
Ahmed Omar
spawn.think@REDACTED
Tue May 17 23:32:19 CEST 2011
Well, it's not the same process. When mnesia find out that :
- there are N of updates to commit,
- the protocol to use it async
- the node of tid is not the local node
it spawns a new process to do the commit.
On Tue, May 17, 2011 at 10:44 PM, John Hughes <john.hughes@REDACTED> wrote:
>
>
>
> *From:* Ahmed Omar <spawn.think@REDACTED>
> **
> I'm not a mnesia expert, but i THINK the race condition is in the test not
> mnesia. transaction is still being committed and logged, when the dirty read
> is issued. if you add a sleep in between or better if you use
> mnesia:sync_transaction (
> http://www.erlang.org/doc/man/mnesia.html#sync_transaction-3) instead of
> mnesia:transaction, the test will fail, i.e the case disappear
> isn't that the expected behavior or am i missing something?
>
>
> Adding a sleep (I added a second) or using sync_transaction instead changes
> the behaviour to what I would expect, so it sounds as though you may be
> right about what's happening. But even so, it's not the behaviour I would
> expect, at least!
>
> There isn't any concurrency in the test. There's only distribution--and
> there's only one copy of the table, on the slave node. Isn't it weird that
> when the transaction returns, the SAME process that ran the transaction does
> not see its side effects?
>
> By the way, if I swap the last two operations (which Ulf Wiger suggested),
> then I see the same kind of behaviour... but now the first operation (which
> is now a dirty_read) actually retrieves the deleted tuple from the table,
> while the second operation (now the dirty_next) sees no keys in the table.
>
> This doesn't happen if the table is on the same node as the test is
> executed on, so distribution certainly is not transparent in this case.
>
> John
>
>
>
>
> On Tue, May 17, 2011 at 6:57 PM, John Hughes <john.hughes@REDACTED>wrote:
>
>> 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
>>
>> _______________________________________________
>> erlang-bugs mailing list
>> erlang-bugs@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-bugs
>>
>>
>
>
> --
> Best Regards,
> - Ahmed Omar
> http://nl.linkedin.com/in/adiaa
> Follow me on twitter
> @spawn_think <http://twitter.com/#!/spawn_think>
>
>
--
Best Regards,
- Ahmed Omar
http://nl.linkedin.com/in/adiaa
Follow me on twitter
@spawn_think <http://twitter.com/#!/spawn_think>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-bugs/attachments/20110517/52c511da/attachment.htm>
More information about the erlang-bugs
mailing list