<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=iso-8859-1" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 9.00.8112.16421">
<STYLE></STYLE>
</HEAD>
<BODY 
style="WORD-WRAP: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space" 
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">
  <DIV style="FONT: 10pt arial"> </DIV>
  <DIV 
  style="FONT: 10pt arial; BACKGROUND: #e4e4e4; font-color: black"><B>From:</B> 
  <A title=ulf.wiger@erlang-solutions.com 
  href="mailto:ulf.wiger@erlang-solutions.com">Ulf Wiger</A> </DIV>
  <DIV style="FONT: 10pt arial"> </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> </DIV></BLOCKQUOTE>
<DIV><FONT size=2 face=Arial>Yes, using sync_transaction makes the example 
behave as I would expect. So does doing the guilty operation in a transaction 
instead of as a dirty read or next. So it seems the lesson is: don't use dirty 
operations and transactions together, if you expect a sequential view of the 
data.</FONT></DIV>
<DIV><FONT size=2 face=Arial></FONT> </DIV>
<DIV><FONT size=2 face=Arial>John</FONT></DIV>
<BLOCKQUOTE 
style="BORDER-LEFT: #000000 2px solid; PADDING-LEFT: 5px; PADDING-RIGHT: 0px; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px">
  <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 
    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></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></BLOCKQUOTE></BODY></HTML>