<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&#39;m working on an intermittent failure in NodeMoveAPIPessimisticTest and I think I&#39;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&#39;s not clear to me from the AtomicMap/AtomicHashMap javadoc if this is ok or if it&#39;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.  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.  So that succeeds.  I&#39;m not sure if this is any different from not using an atomic map:</div>

<div><br></div><div>1.  tx1: cache.get(k, v); // reads into tx context</div><div>2.  tx2: cache.get(k, v);</div><div>3.  tx1: cache.put(k, v + 1 );</div><div>4.  tx1: commit</div><div>5.  tx2: cache.put(k, v + 1 );</div>
<div>
6.  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&#39;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 &quot;map.put(subkey2, value)&quot;. Tx2 doesn&#39;t touch subkey1, so it&#39;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&#39;t think it&#39;s what most users would expect. (The proof, I guess, is in the current implementation of TreeCache.move()).<br>

<br></div><div>With a FineGrainedAtomicMap in optimistic mode, it&#39;s not obvious why tx1 writing to subkey1 should cause tx2&#39;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><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 (&quot;tx2: am2.get(subkey1)&quot;). I&#39;m pretty sure that&#39;s a bug and I fixed it locally by using the FORCE_WRITE_LOCK in AtomicHashMapProxy.getDeltaMapForWrite. </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&#39;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&#39;s way too easy to introduce a read of a node&#39;s structure in a transaction and start losing data without knowing it.<br>

</div><div><br></div></div></div></div>