[infinispan-issues] [JBoss JIRA] (ISPN-2956) putIfAbsent on Hot Rod Java client doesn't reliably fulfil contract
Galder Zamarreño (JIRA)
issues at jboss.org
Wed Jun 18 03:23:25 EDT 2014
[ https://issues.jboss.org/browse/ISPN-2956?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12977242#comment-12977242 ]
Galder Zamarreño commented on ISPN-2956:
----------------------------------------
After trying the solution mentioned above, it became clear that it'd only work for those situations where the previous value was non-existent, e.g. for putIfAbsent() operations, so this option has been abandoned. As indicated in the mail thread (see http://lists.jboss.org/pipermail/infinispan-dev/2014-June/015079.html), the return of all conditional operations, including putIfAbsent(), and those that return previous value, can only be guaranteed when the cache is transactional and the rollback phase can guarantee that state is not partially applied. The pull request about to be sent adds some tests that verify this, and adds warn messages when either conditional operations or previous values need to be returned, and the cache is not transactional.
> putIfAbsent on Hot Rod Java client doesn't reliably fulfil contract
> -------------------------------------------------------------------
>
> Key: ISPN-2956
> URL: https://issues.jboss.org/browse/ISPN-2956
> Project: Infinispan
> Issue Type: Bug
> Security Level: Public(Everyone can see)
> Components: Remote Protocols
> Reporter: Galder Zamarreño
> Assignee: Galder Zamarreño
> Labels: 63gablocker, hotrod-java-client, remote-clients
> Fix For: 7.0.0.Beta1
>
>
> Hot Rod's putIfAbsent might have issues on some edge cases:
> {quote}I want to know whether the putting entry already exists in the remote
> cache cluster, or not.
> I thought that RemoteCache.putIfAbsent() would be useful for that
> purpose, i.e.,
> {code}
> if (remoteCache.putIfAbsent(k,v) == null) {
> // new entry.
> } else {
> // k already exists.
> }
> {code}
> But no.
> The putIfAbsent() for new entry may return non-null value, if one of the
> server crushed while putting.
> The behavior is like the following:
> 1. Client do putIfAbsent(k,v).
> 2. The server receives the request and sends replication requests to
> other servers. If the server crushed before completing replication, some
> servers own that (k,v), but others not.
> 3. Client receives the error. The putIfAbsent() internally retries the
> same request to the next server in the cluster server list.
> 4. If the next server owns the (k,v), the putIfAbsent() returns the
> replicated (k,v) at the step 2, without any error.
> So, putIfAbsent() is not reliable for knowing whether the putting entry
> is *exactly* new or not.
> Does anyone have any idea/workaround for this purpose?{quote}
> A workaround is to do this:
> {quote}We got a simple solution, which can be applied to our customer's application.
> If each value part of putting (k,v) is unique or contains unique value,
> the client can do *double check* wether the entry is new.
> {code}
> val = System.nanoTime(); // or uuid is also useful.
> if ((ret = cache.putIfAbsent(key, val)) == null
> || ret.equals(val)) {
> // new entry, if the return value is just the same.
> } else {
> // key already exists.
> }
> {code}
> We are proposing this workaround which almost works fine.{quote}
> However, this is a bit of a cludge.
> Hot Rod should be improved with an operation that allows a version to be passed when entry is created, instead of relying on the client generating it.
--
This message was sent by Atlassian JIRA
(v6.2.6#6264)
More information about the infinispan-issues
mailing list