<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br><br>Sent from my iPhone</div><div><br>On 20 May 2013, at 12:58, Dan Berindei &lt;<a href="mailto:dan.berindei@gmail.com">dan.berindei@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, May 20, 2013 at 1:57 PM, Manik Surtani <span dir="ltr">&lt;<a href="mailto:msurtani@redhat.com" target="_blank">msurtani@redhat.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><div class="im"><div>On 16 May 2013, at 15:04, Dan Berindei &lt;<a href="mailto:dan.berindei@gmail.com" target="_blank">dan.berindei@gmail.com</a>&gt; wrote:</div>

<br></div><div class="im"><blockquote type="cite"><div dir="ltr"><div><div><div><div><div><div><div><div><div>Hi guys<br><br></div>I'm working on an intermittent failure in NodeMoveAPIPessimisticTest and I think I've come across what I think is underspecified behaviour in AtomicHashMap.<br>



<br></div>Say we have two transactions, tx1 and tx2, and they both work with the same atomic map in a pessimistic cache:<br><br></div>1. tx1: am1 = AtomicMapLookup.get(cache, key)<br></div>2. tx2: am2 = AtomicMapLookup.get(cache, key)<br>



</div>3. tx1: am1.put(subkey1, value1) // locks the map<br></div>4. tx2: am2.get(subkey1) // returns null<br></div>5. tx1: commit // the map is now {subkey1=value1}<br></div>6. tx2: am2.put(subkey2, value2) // locks the map<br>



</div>7. tx2: commit // the map is now {subkey2=value2}<br><div><br><div><div>It's not clear to me from the AtomicMap/AtomicHashMap javadoc if this is ok or if it's a bug...<br></div></div></div></div></blockquote>

<div><br></div></div><div>If optimistic, step 7 should fail with a write skew check. &nbsp;If pessimistic, step 2 would *usually* block assuming that another thread is updating the map, but since neither tx1 or tx2 has started updating the map yet, neither has a write lock on the map. &nbsp;So that succeeds. &nbsp;I'm not sure if this is any different from not using an atomic map:</div>

<div><br></div><div>1. &nbsp;tx1: cache.get(k, v); // reads into tx context</div><div>2. &nbsp;tx2: cache.get(k, v);</div><div>3. &nbsp;tx1: cache.put(k, v + 1 );</div><div>4. &nbsp;tx1: commit</div><div>5. &nbsp;tx2: cache.put(k, v + 1 );</div>
<div>
6. &nbsp;tx2: commit</div><div><br></div><div>here as well, if using optimistic, step 6 will fail with a WSC but if pessimistic this will work (since tx2 only requested a write lock after tx1 committed/released its write lock).</div>

<div class="im"><br></div></div></div></blockquote><div><br></div><div>The difference is that in your scenario, you see in the code that tx2 writes to key k, so it's not surprising to find that tx2 overwrote the value written by tx1. But it would be surprising if tx2 also overwrote an unrelated key k2.<br>

<br>With an atomic map, you only see in the code "map.put(subkey2, value)". Tx2 doesn't touch subkey1, so it's not that obvious that it should remove it. It is clear to me why it behaves the way it does now, after reading the implementation, but I don't think it's what most users would expect. (The proof, I guess, is in the current implementation of TreeCache.move()).<br></div></div></div></div></div></blockquote>+1 and nice explanatiom :-)<br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>

<br></div><div>With a FineGrainedAtomicMap in optimistic mode, it's not obvious why tx1 writing to subkey1 should cause tx2's write to subkey2 fail, either (see <a href="https://issues.jboss.org/browse/ISPN-3123">https://issues.jboss.org/browse/ISPN-3123</a>).<br></div></div></div></div></div></blockquote><div>+1</div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>

</div><div>&nbsp;</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div class="im"><blockquote type="cite"><div dir="ltr">

<div><div><div>Note that today the map is overwritten by tx2 even without step 4 ("tx2: am2.get(subkey1)"). I'm pretty sure that's a bug and I fixed it locally by using the FORCE_WRITE_LOCK in AtomicHashMapProxy.getDeltaMapForWrite.&nbsp;</div>

<div>

<br>However, when the Tree API moves a node it first checks for the existence of the destination node, which means NodeMoveAPIPessimisticTest is still failing. I'm not sure if I should fix that by forcing a write lock for all AtomicHashMap reads, for all TreeCache reads, or only in TreeCache.move().<br>

</div></div></div></div></blockquote><div><br></div></div>I think only in TreeCache.move()</div><div><br></div></div></blockquote><div><br></div><div>I tend to disagree. I think it's way too easy to introduce a read of a node's structure in a transaction and start losing data without knowing it.<br>

</div><div><br></div></div></div></div>
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>infinispan-dev mailing list</span><br><span><a href="mailto:infinispan-dev@lists.jboss.org">infinispan-dev@lists.jboss.org</a></span><br><span><a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a></span></div></blockquote></body></html>