<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On 8 Apr 2011, at 18:30, Emmanuel Bernard wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Yes I think that would fit the bill. Let me give some more background<div><br></div><div><b>Background</b><br>In Hibernate OGM, we store collections in a single key essentially as a Set&lt;Map&lt;String,Object&gt;&gt; ie as a set of tuples, esch tuple representing the equivalent of one row of an association table in a&nbsp;relational database. The reason for that is to be able to get the collection state by doing key lookups. If we were to store each tuple of the collection in a separate key, we would have no way to get&nbsp;the list of matching keys for a given collection (unless you get a key with the list of keys for a collection but then you are just moving the problem instead of fixing it.<br><br>Today, we reach scalability problems very quickly as we end up touching the collection key every time one entity is added or removed from it. In a relational database, this operation scale quite&nbsp;well as locks are acquired on each tuple and not on the whole tupes for a given collection.<br><br>What we could do is:<br>&nbsp;- use AtomicMap&lt;UUID,Map&lt;String,Object&gt;&gt; instead of Set&lt;Map&lt;String,Object&gt;&gt;<br>&nbsp;- trick infinispan so that it believes that the atomic lock is held at the atomic map key level rather than the atomic map as a whole.<br><br>Many operations could be done consecutively:<br>&nbsp;- update k1 in T1 and k2 in T2 in concurrently<br>&nbsp;- add k1 in T1 and remove k2 in T2 concurrently<br>etc<br>what would still fail is:<br>&nbsp;- modify k1 in T1 and k1 in T2 concurrently<br><br></div></div></blockquote>You'd get this by using a Cache&lt;UUID, Map&lt;String, Object&gt;&gt;, together with fine grained replication.&nbsp;<br><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><b>Solution</b><br>The approach Sanne proposes would solve our use case.</div><div>To refine a bit the API:</div><div>&nbsp;- to avoid the exception, you could return a boolean for success or failure</div><div>&nbsp;- you could have DeltaAware merge(DeltaAware... deltaAwareOps)</div><div>&nbsp;- I am not entirely sure you need the old value in our use case but that seems like a good idea generally speaking even if that makes the algorithm more complex I suspect as ISPN needs to find the common ancestor</div><div><br></div><div>Emmanuel</div><div><br></div><div><br><div><div>On 8 avr. 2011, at 19:07, Sanne Grinovero wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Hi Mircea,<br>I remember you recently mentioned that you have been looking into ways<br>to give the ability to the application to resolve updating conflicts.<br>I don't think you where referring to AtomicMap or any other DeltaAware<br>specifically, but it seems now that we urgently need something like<br>this in OGM.<br><br>I'm looking into the Delta interface, which defines this single method:<br><br>DeltaAware merge(DeltaAware d);<br><br>This looks great to merge an update onto an existing value; But of<br>course the world is made of parallel executing updates, especially so<br>when transactions are involved, so we would like to be able to deal<br>with multiple concurrent updates being applied on the same read value.<br><br>I'm wondering if we could get something like<br><br>DeltaAware merge(DeltaAware originalValue, DeltaAware updateA,<br>DeltaAware updateB) throws UnsolvableConflict;<br><br>As Emmanuel pointed out while implementing OGM, if two different<br>updates are being applied to an AtomicMap, it's possible that the<br>updates relate to different keys in the AtomicMap, and for the OGM<br>usecase we would be totally fine with that and would *not* like the<br>transaction to be rolled back. From my understanding of AtomicMap, if<br>two different keys are changed one transaction will fail (correct?).<br>Of course it's totally possible that both updates where going to<br>affect the same keys, and in this case we want to have the operation<br>rolled back.<br><br>I don't mean the API I wrote literally, I wrote it like that just to<br>give a general picture of what we need; I'm not really liking the idea<br>of throwing an exception on a potentially frequently occurring event,<br>and also while you could chain such invocations in case of multiple<br>updates arriving on the same key, I think it would be far better to be<br>able to try different combinations - or let the application try to be<br>clever - to try resolving as much non conflicting DeltaAware updates<br>as possible.<br><br>Considering that each transaction might change multiple keys, it would<br>be awesome to describe the API in such a way that either Infinispan or<br>the application can be "smart" and be able to estimate which<br>transaction could be removed (rolled back) to provide the minimum<br>amount of rolled back transactions. I'm not even sure the policy<br>should favour the maximum amount of transactions, maybe the<br>application wants to favour the highest possible changeset, or a<br>specific important one.<br><br>Even if we start just implementing the method signature I proposed,<br>that could bring a hell of scalability improvements; possibly not only<br>to HibernateOGM but as far as I understood the TreeCache as well.<br><br>Ideas?<br><br>Emmanuel, do you agree this would fit the HibernateOGM needs?<br><br>Cheers,<br>Sanne<br></div></blockquote></div><br></div></div>_______________________________________________<br>infinispan-dev mailing list<br><a href="mailto:infinispan-dev@lists.jboss.org">infinispan-dev@lists.jboss.org</a><br>https://lists.jboss.org/mailman/listinfo/infinispan-dev</blockquote></div><br></body></html>