<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>