On 03/21/2017 04:37 PM, William Burns wrote:
Some users have expressed the need to have some sort of forEach
operation that is performed where the Consumer is called while holding
the lock for the given key and subsequently released after the
Consumer operation completes.
Seconding Dan's question - is that intended to be able to modify the
entry? In my opinion, sending a function that will work on the
ReadWriteEntryView directly to the node is the only reasonable request.
I wouldn't like to see blocking operations in there.
Due to the nature of how streams work with retries and performing the
operation on the primary owner, this works out quite well with forEach
to be done in an efficient way.
The problem is that this only really works well with non tx and
pessimistic tx. This obviously leaves out optimistic tx, which at
first I was a little worried about. But after thinking about it more,
this prelocking and optimistic tx don't really fit that well together
anyways. So I am thinking whenever this operation is performed it
would throw an exception not letting the user use this feature in
optimistic transactions.
How exactly reading streams interacts with transactions? Does it wrap
read entries into context? This would be a scalability issue.
I agree that "locking" should not be exposed with optimistic transactions.
With pessimistic transactions, how do you expect to handle locking
order? For regular operations, user is responsible for setting up some
locking order in order to not get a deadlock. With pessimistic
transaction, it's the cache itself who will order the calls. Also, if
you lock anything that is read, you just end up locking everything (or,
getting a deadlock). If you don't it's the same as issuing the lock and
reading again (to check the locked value) - but you'd do that internally
anyway. Therefore, I don't feel well about pessimistic transactions neither.
Another question is what does the API for this look like. I was
debating between 3 options myself:
1. AdvancedCache.forEachWithLock(BiConsumer<Cache, CacheEntry<K, V>>
consumer)
This require the least amount of changes, however the user can't
customize certain parameters that CacheStream currently provides
(listed below - big one being filterKeys).
2. CacheStream.forEachWithLock(BiConsumer<Cache, CacheEntry<K, V>>
consumer)
This method would only be allowed to be invoked on the Stream if no
other intermediate operations were invoked, otherwise an exception
would be thrown. This still gives us access to all of the CacheStream
methods that aren't on the Stream interface (ie.
sequentialDistribution, parallelDistribution, parallel, sequential,
filterKeys, filterKeySegments, distributedBatchSize,
disableRehashAware, timeout).
For both options, I don't like Cache being passed around. You should
modify the CacheEntry (or some kind of view) directly.
Radim
3. LockedStream<CacheEntry<K, V>> AdvancedCache.lockedStream()
This requires the most changes, however the API would be the most
explicit. In this case the LockedStream would only have the methods on
it that are able to be invoked as noted above and forEach.
I personally feel that #3 might be the cleanest, but obviously
requires adding more classes. Let me know what you guys think and if
you think the optimistic exclusion is acceptable.
Thanks,
- Will
_______________________________________________
infinispan-dev mailing list
infinispan-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/infinispan-dev
--
Radim Vansa <rvansa(a)redhat.com>
JBoss Performance Team