<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br></div><div>Well, it's the same process that's calling the functions, so usually one would expect a sequential view of the data.</div><div><br></div><div>However, in the case of transactions vs dirty, it's not quite as clear-cut, and I don't think the documentation has anything to say about this. except to hint that it's unhealthy to mix dirty and transactions too much.</div><div><br></div><div>I would agree with John that this behaviour is surprising on the surface of it. Perhaps using mnesia:activity(sync_transaction, F) or mnesia:sync_transaction(F) * would make a difference? I'll admit that I haven't tried.</div><div><br></div><div>* According to the User Guide, "Synced transactions waits until all active replicas has committed the transaction (to disc) before returning from the mnesia:sync_transaction call."</div><div><br></div><div>BR,</div><div>Ulf W</div><div><br></div><div><div>On 17 May 2011, at 23:32, Ahmed Omar wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">Well, it's not the same process. When mnesia find out that :<div>- there are N of updates to commit, </div><div>- the protocol to use it async </div><div>- the node of tid is not the local node </div><div> </div><div>
it spawns a new process to do the commit.<br><br><div class="gmail_quote">On Tue, May 17, 2011 at 10:44 PM, John Hughes <span dir="ltr"><<a href="mailto:john.hughes@quviq.com">john.hughes@quviq.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div bgcolor="#ffffff">
<div><font size="2" face="Arial"></font> </div>
<blockquote style="border-left:#000000 2px solid;padding-left:5px;padding-right:0px;margin-left:5px;margin-right:0px" dir="ltr">
<div style="font:10pt arial"> </div>
<div style="font:10pt arial;background:#e4e4e4"><b>From:</b>
<a title="spawn.think@gmail.com" href="mailto:spawn.think@gmail.com" target="_blank">Ahmed
Omar</a> </div><div class="im">
<div><strong><font size="2" face="Arial"></font></strong><br></div>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 (<a href="http://www.erlang.org/doc/man/mnesia.html#sync_transaction-3" target="_blank">http://www.erlang.org/doc/man/mnesia.html#sync_transaction-3</a>) instead
of mnesia:transaction, the test will fail, i.e the case disappear
<div>isn't that the expected behavior or am i missing something?</div>
<div> </div></div></blockquote>
<div dir="ltr"><font size="2" face="Arial">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!</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">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?</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">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.</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">This doesn't happen if the table is on the same
node as the test is executed on, so </font><font size="2" face="Arial">distribution
certainly is not transparent in this case.</font></div>
<div><font size="2" face="Arial"></font> </div><font color="#888888">
<div><font size="2" face="Arial">John</font></div></font><div><div></div><div class="h5">
<div> </div>
<div dir="ltr"><br></div>
<blockquote style="border-left:#000000 2px solid;padding-left:5px;padding-right:0px;margin-left:5px;margin-right:0px" dir="ltr">
<div><font face="Verdana, Arial, Helvetica, sans-serif"><br></font><br>
<div class="gmail_quote">On Tue, May 17, 2011 at 6:57 PM, John Hughes <span dir="ltr"><<a href="mailto:john.hughes@quviq.com" target="_blank">john.hughes@quviq.com</a>></span>
wrote:<br>
<blockquote style="border-left:#ccc 1px solid;margin:0px 0px 0px 0.8ex;padding-left:1ex" class="gmail_quote">
<div bgcolor="#ffffff">
<div><font size="2" face="Arial">QuickCheck turned up another case of odd
behaviour at Klarna.</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">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?</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">Here's the test:</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">test() -><br> Slave =
start_mnesia_with_slave(),<br> {atomic,ok} =
mnesia:create_table(rec,[{type,set},<br>
{disc_only_copies,[Slave]}]),<br>
ok =
mnesia:dirty_write({rec,4,1}),<br> %% The next command
MUST be done in a transaction, otherwise dirty_next
works<br> {atomic,ok} =
mnesia:transaction(fun()->mnesia:delete_object({rec,4,1})
end),<br> %% Here's the problem: dirty_next returns 4, but
this key is not in the table!<br>
4 =
mnesia:dirty_next(rec,0),<br>
[] =
mnesia:dirty_read(rec,4).<br></font></div>
<div><font size="2" face="Arial">I'm starting mnesia and the slave node like
this:</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">start_mnesia_with_slave()
-><br> {ok,Dir} = file:get_cwd(),<br>
ok = error_logger:tty(false),<br>
mnesia:stop(),<br> ok =
error_logger:tty(true),<br>
delete_file("mnesia"),<br>
delete_file("slave"),<br> ok =
file:make_dir("mnesia"),<br> ok =
file:make_dir("slave"),<br> Slave =
slave(),<br> ok =
application:set_env(mnesia,dir,Dir++"/mnesia"),<br> ok =
rpc:call(Slave,application,set_env,[mnesia,dir,Dir++"/slave"]),<br>
ok = mnesia:create_schema([node(),Slave]),<br> ok =
mnesia:start(),<br> ok =
rpc:call(Slave,mnesia,start,[]),<br> Slave.</font></div>
<div> </div>
<div><font size="2" face="Arial">slave() -><br> case
slave:start_link(net_adm:localhost(),"slave") of<br> {ok,Slave}
-><br>
Slave;<br> {error,{already_running,Slave}}
-><br> Slave<br>
end.<br></font></div>
<div><font size="2" face="Arial">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.</font></div>
<div><font size="2" face="Arial"></font> </div>
<div><font size="2" face="Arial">delete_file(Name) -><br>
case filelib:is_dir(Name) of<br> true -><br>
[delete_file(Name++"/"++X) || X <-
list_dir(Name)],<br>
file:del_dir(Name),<br>
delete_file(Name);<br> {error,eaccess}
-><br> delete_file(Name);<br> {error,enoent}
-><br> io:format("Could not find
~p\n",[Name]),<br> ok;<br> false
-><br> case file:delete(Name)
of<br> {error,enoent} -><br>
ok;<br> {error,eacces} -><br>
io:format("Could not access ~p\n",[Name]),<br>
delete_file(Name);<br> ok -><br>
delete_file(Name)<br> end<br>
end.</font></div>
<div> </div>
<div><font size="2" face="Arial">list_dir(Name) -><br> case
file:list_dir(Name) of<br> {ok,Files} -><br>
Files;<br> {error,eacces} -><br>
io:format("Could not list directory
~p\n",[Name]),<br>
list_dir(Name);<br> {error,enoent} -><br>
io:format("Could not find directory
~p\n",[Name]),<br> []
<br> end.<br></font></div><font color="#888888">
<div><font size="2" face="Arial">John</font></div></font></div><br>_______________________________________________<br>erlang-bugs
mailing list<br><a href="mailto:erlang-bugs@erlang.org" target="_blank">erlang-bugs@erlang.org</a><br><a href="http://erlang.org/mailman/listinfo/erlang-bugs" target="_blank">http://erlang.org/mailman/listinfo/erlang-bugs</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Best Regards,<br>- Ahmed Omar
<div><a href="http://nl.linkedin.com/in/adiaa" target="_blank">http://nl.linkedin.com/in/adiaa</a></div>
<div>Follow me on twitter</div>
<div><a href="http://twitter.com/#!/spawn_think" target="_blank">@spawn_think</a></div><br></div></blockquote></div></div></div>
</blockquote></div><br><br clear="all"><br>-- <br>Best Regards,<br>- Ahmed Omar<div><a href="http://nl.linkedin.com/in/adiaa" target="_blank">http://nl.linkedin.com/in/adiaa</a></div><div>Follow me on twitter</div><div><a href="http://twitter.com/#!/spawn_think" target="_blank">@spawn_think</a></div>
<br>
</div>
_______________________________________________<br>erlang-bugs mailing list<br><a href="mailto:erlang-bugs@erlang.org">erlang-bugs@erlang.org</a><br>http://erlang.org/mailman/listinfo/erlang-bugs<br></blockquote></div><br><div>
<div>Ulf Wiger, CTO, Erlang Solutions, Ltd.</div><div><a href="http://erlang-solutions.com">http://erlang-solutions.com</a></div><div><br></div><br class="Apple-interchange-newline">
</div>
<br></body></html>