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?


>
>>
>> Sanne
>>
>> 2011/7/4 Galder Zamarreño <gal...@redhat.com>:
>>> Do these atomic operations really make sense within an (optimitic) 
>>> transaction?
>>>
>>> For example, putIfAbsent(): it stores a k,v pair if the key is not present. 
>>> But the key about it's usability is that the return of putIfAbsent can tell 
>>> you whether the put succeeded or not.
>>>
>>> Once you go into transactions, the result is only valid once the 
>>> transaction has been prepared unless the pessimistic locking as per 
>>> definition in http://community.jboss.org/docs/DOC-16973 is in use, and 
>>> that's already pretty confusing IMO.
>>>
>>> I get the feeling that those atomic operations are particularly useful when 
>>> transactions are not used cos they allow you to reduce to cache operations 
>>> to one, hence avoiding the need to use a lock or synchronized block, or in 
>>> our case, a transaction.
>>>
>>> On Jun 30, 2011, at 3:11 PM, Sanne Grinovero wrote:
>>>
>>>> Hello all,
>>>> some team members had a meeting yesterday, one of the discussed
>>>> subjects was about using atomic operations (putIfAbsent, etc..).
>>>> Mircea just summarised it in the following proposal:
>>>>
>>>> The atomic operations, as defined by the ConcurrentHashMap, don't fit
>>>> well within the scope of optimistic transaction: this is because there
>>>> is a discrepancy between the value returned by the operation and the
>>>> value and the fact that the operation is applied or not:
>>>> E.g. putIfAbsent(k, v) might return true as there's no entry for k in
>>>> the scope of the current transaction, but in fact there might be a
>>>> value committed by another transaction, hidden by the fact we're
>>>> running in repeatable read mode.
>>>> Later on, at prepare time when the same operation is applied on the
>>>> node that actually holds k, it might not succeed as another
>>>> transaction has updated k in between, but the return value of the
>>>> method was already evaluated long before this point.
>>>> In order to solve this problem, if an atomic operations happens within
>>>> the scope of a transaction, Infinispan eagerly acquires a lock on the
>>>> remote node. This locks is held for the entire duration of the
>>>> transaction, and is an expensive lock as it involves an RPC. If
>>>> keeping the lock remotely for potentially long time represents a
>>>> problem, the user can suspend the running transaction and run the
>>>> atomic operation out of transaction's scope, then resume the
>>>> transaction.
>>>>
>>>>
>>>> In addition to this, would would you think about adding a flag to
>>>> these methods which acts as suspending the transaction just before and
>>>> resuming it right after? I don't know what is the cost of suspending &
>>>> resuming a transaction, but such a flag could optionally be optimized
>>>> in future by just ignoring the current transaction instead of really
>>>> suspending it, or apply other clever tricks we might come across.
>>>>
>>>> I also think that we should discuss if such a behaviour should not be
>>>> the default - anybody using an atomic operation is going to make some
>>>> assumptions which are clearly incompatible with the transaction, so
>>>> I'm wondering what is the path here to "least surprise" for default
>>>> invocation.
>>>>
>>>> Regards,
>>>> Sanne
>>>> _______________________________________________
>>>> infinispan-dev mailing list
>>>> infinispan-dev@lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>>>
>>> --
>>> Galder Zamarreño
>>> Sr. Software Engineer
>>> Infinispan, JBoss Cache
>>>
>>>
>>> _______________________________________________
>>> 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
>
> --
> Galder Zamarreño
> Sr. Software Engineer
> Infinispan, JBoss Cache
>
>
> _______________________________________________
> 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