On 5 Jul 2011, at 11:39, Sanne Grinovero wrote:

> 2011/7/5 Dan Berindei <dan.berin...@gmail.com>:
>> On Tue, Jul 5, 2011 at 12:46 PM, Sanne Grinovero <sa...@infinispan.org> 
>> wrote:
>>> 2011/7/5 Galder Zamarreño <gal...@redhat.com>:
>>>> 
>>>> 
>>>> On Jul 4, 2011, at 11:25 AM, Sanne Grinovero wrote:
>>>> 
>>>>> I agree they don't make sense, but only in the sense of exposed API
>>>>> during a transaction: some time ago I admit I was expecting them to
>>>>> just work: the API is there, nice public methods in the public
>>>>> interface with javadocs explaining that that was exactly what I was
>>>>> looking for, no warnings, no failures. Even worse, all works fine when
>>>>> running a local test because how the locks currently work they are
>>>>> acquired locally first, so unless you're running such a test in DIST
>>>>> mode, and happen to be *not* the owner of the being tested key, people
>>>>> won't even notice that this is not supported.
>>>>> 
>>>>> Still being able to use them is very important, also in combination
>>>>> with transactions: I might be running blocks of transactional code
>>>>> (like a CRUD operation via OGM) and still require to advance a
>>>>> sequence for primary key generation. This needs to be an atomic
>>>>> operation, and I should really not forget to suspend the transaction.
>>>> 
>>>> Fair point. At first glance, the best way to deal with this is suspending 
>>>> the tx cos that guarantees the API contract while not forcing locks to be 
>>>> acquired for too long.
>>>> 
>>>> I'd advice though that whoever works on this though needs to go over 
>>>> existing use cases and see if the end result could differ somehow if this 
>>>> change gets applied. If any divergences are found and are to be expected, 
>>>> these need to be thoroughly documented.
>>>> 
>>>> I've gone through some cases and end results would not differ at first 
>>>> glance if the atomic ops suspend the txs. The only thing that would change 
>>>> would be the expectations of lock acquisition timeouts by atomic ops 
>>>> within txs.
>>>> 
>>>> For example:
>>>> 
>>>> Cache contains: k1=galder
>>>> 
>>>> 1. Tx1 does a cache.replace(k1, "galder", "sanne") -> suspends tx and 
>>>> applies change -> k1=sanne now
>>>> 2. Tx2 does a cache.replace(k1, "galder", "manik") -> suspends tx and is 
>>>> not able to apply change
>>>> 3. Tx2 commits
>>>> 4. Tx1 commits
>>>> End result: k1=sanne
>>> 
>>> Right.
>>> To clarify, this is what would happen with the current implementation:
>>> 
>>> 1. Tx2 does a cache.get(k1) -> it reads the value of k1, and is
>>> returned "galder"
>>> 2. Tx1 does a cache.replace(k1, "galder", "sanne") -> k1="sanne" in
>>> the scope of this transaction, but not seen by other tx
>>> 3. Tx2 does a cache.replace(k1, "galder", "manik") -> k1="manik" is
>>> assigned, as because of repeatable read we're still seeing "galder"
>>> 4. Tx2  & Tx1 commit
>>> 
>>> ..and the end result depends on who commits first.
>>> 
>>>> 
>>>> 1. Tx1 does a cache.replace(k1, "galder", "sanne") -> acquires lock
>>>> 2. Tx2 does a cache.replace(k1, "galder", "manik") -> waits for lock
>>>> 3. Tx2 rollback -> times out acquiring lock
>>>> 4. Tx1 commits -> applies change
>>>> End result: k1=sanne
>>> 
>>> I'm not sure we're on the same line here. 1) should apply the
>>> operation right away, so even if it might very briefly have to acquire
>>> a lock on it, it's immediately released (not at the end of the
>>> transaction), so why would TX2 have to wait for it to the point it
>>> needs to rollback?
>>> 
>> 
>> I think it would make sense to make atomic operations pessimistic by
>> default, so they would behave like in Galder's example.
>> 
>> Then if you wanted to reduce contention you could suspend/resume the
>> transaction around your atomic operations and make them behave like
>> you're expecting them to.
>> 
>> Here is a contrived example:
>> 
>> 1. Start tx Tx1
>> 2. cache.get("k") -> "v0"
>> 3. cache.replace("k", "v0", "v1")
>> 4. gache.get("k") -> ??
>> 
>> With repeatable read and suspend/resume around atomic operations, I
>> believe operation 4 would return "v0", and that would be very
>> surprising for a new user.
>> So I'd rather require explicit suspend/resume calls to make sure
>> anyone who uses atomic operations in a transaction understands what
>> results he's going to get.
> 
> The problem is that as a use case it makes no sense to use an atomic
> operation without evaluating the return value.
> so 3) should actually read like
> `
> 3. boolean done = cache.replace("k", "v0", "v1")
> and based on this value, the application would branch in some way, and
> so acquiring locks and waiting for each other is not enough, we can
> only support this if write skew checks are enabled, and mandate the
> full operation to rollback in the end. That might be one option, but I
> really don't like to make it likely to rollback transactions,
then you can suspend the transaction and run the atomic operation out of tx's 
scope. 
> I'd
> prefer to have an alternative like a new flag which enforces a "fresh
> read" skipping the repeatable read guarantees. Of course this wouldn't
> work if we're not actually sending the operations to the key owners,
> so suspending the transaction is a much nicer approach from the user
> perspective. Though I agree this behaviour should be selectable.
> 
> Cheers,
> Sanne
> 
>> 
>> Dan
>> 
>> _______________________________________________
>> infinispan-dev mailing list
>> infinispan-dev@lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>> 
> 
> _______________________________________________
> infinispan-dev mailing list
> infinispan-dev@lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/infinispan-dev


_______________________________________________
infinispan-dev mailing list
infinispan-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/infinispan-dev

Reply via email to