Neat! Just tried quickly and seems to work on ISPN test... I'll see if it works 
in 2LC and if so I'll send a PR. 

We can then inspect where else this check might be needed.

Cheers,
--
Galder Zamarreño
Infinispan, Red Hat

> On 27 Feb 2017, at 14:01, Radim Vansa <rva...@redhat.com> wrote:
> 
> Hi Galder,
> 
> another solution came upon my mind (actually after finding this SO 
> question [1]): we could check if
> 
> (this.key == key || this.key.equals(key))
> 
> in SingleKeyNonTxInvocation context instead of just
> 
> this.key.equals(key)
> 
> and that could do the trick. Plus, such check maybe needed in couple of 
> other places, haven't tried that.
> 
> Seems that HashMap already does so, so the other types of contexts 
> should work OOTB.
> 
> Radim
> 
> [1] 
> http://stackoverflow.com/questions/13521184/equals-returns-false-yet-object-is-found-in-map
> 
> On 02/20/2017 05:22 PM, Radim Vansa wrote:
>> On 02/20/2017 03:52 PM, Galder Zamarreño wrote:
>>> I've just verified the problem and the NPE can be reproduced with 
>>> Infinispan alone.
>>> 
>>> More replies below:
>>> 
>>> --
>>> Galder Zamarreño
>>> Infinispan, Red Hat
>>> 
>>>> On 16 Feb 2017, at 10:44, Radim Vansa <rva...@redhat.com> wrote:
>>>> 
>>>> On 02/15/2017 06:07 PM, Galder Zamarreño wrote:
>>>>> --
>>>>> Galder Zamarreño
>>>>> Infinispan, Red Hat
>>>>> 
>>>>>> On 15 Feb 2017, at 12:21, Radim Vansa <rva...@redhat.com> wrote:
>>>>>> 
>>>>>> On 02/15/2017 11:28 AM, Galder Zamarreño wrote:
>>>>>>> Hey Radim,
>>>>>>> 
>>>>>>> Your changes in ISPN-7029 are causing issues with Hibernate 2LC.
>>>>>>> 
>>>>>>> In particular [2]. Name.equals() always returns false, so it'll never 
>>>>>>> be found in the context. So entry is null.
>>>>>> That's obviously a bug in the 2LC testsuite, isn't it?
>>>>> LOL, is it? You added the class and the javadoc clearly states that this 
>>>>> entity defines equals incorrectly. You must have added it for a reason?
>>>>> 
>>>>> https://github.com/hibernate/hibernate-orm/blob/master/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/entities/Name.java
>>>>> 
>>>>> In any case, an object with an incorrect equals impl should not result in 
>>>>> an NPE within Infinispan :|
>>>>> 
>>>>>> Object used as @EmbeddedId needs to have the equals correctly defined. 
>>>>>> How else would you compare ids? I wonder how could that work in the past.
>>>>> ROFL... it's your baby so you tell me ;)
>>>> Okay, okay - I haven't checked the javadoc, so I just assumed that it's an 
>>>> oversight :)
>>>> 
>>>>>>> Moreover, if EntryLookup.lookupEntry javadoc (and some implementations) 
>>>>>>> can and do return null. Are you expecting that somehow that method will 
>>>>>>> never return null?
>>>>>> With ISPN-7029 in, the entry should be wrapped in the context after 
>>>>>> EntryWrappingInterceptor if the key is in readCH, otherwise it should be 
>>>>>> null. In case that xDistributionInterceptor finds out that it needs to 
>>>>>> work on that value despite not being able to read it (e.g. in case that 
>>>>>> it's in writeCH during unfinished rebalance), it should wrap 
>>>>>> NullCacheEntry.getInstance() using EntryFactory. wrapExternalEntry. More 
>>>>>> info about the logic is in o.i.c.EntryFactory javadoc [3].
>>>>> Not sure I understand what you're trying to imply above... so, is 
>>>>> lookupEntry() allowed to return null or not?
>>>> It is allowed to return null, but:
>>>> 
>>>> 1. If the node is an owner according to readCH, the entry must be wrapped 
>>>> into context in EWI (possibly as NullCacheEntry).
>>>> 2. The code can reach the GKVC.perform() iff this node is an owner of 
>>>> given key.
>>>> 
>>>> The problem here is that I've assumed that if the entry was wrapped, it 
>>>> can be fetched. With incorrectly defined equals, as we see here, this does 
>>>> not hold. So we can
>>>> 
>>>> a) check if the entry is null and throw more explanatory exception - more 
>>>> code in perform()
>>>> b) do the lookup after wrapping and throw there - unnecessary map lookup 
>>>> for such annoying problem
>>>> c) ostrich approach
>>>> 
>>>> I think that b) in assert could do, otherwise I'd suggest c)
>>> Hmmmmm, what about not throwing an exception at all?
>>> 
>>> IOW, e.g. in SingleKeyNonTxInvocationContext.lookupEntry(), if the key is 
>>> not equals to the one cached, but the cached one is NullCacheEntry, 
>>> couldn't it return that instead of null? What I'm trying to achieve here is 
>>> that if the equals is not correctly implemented, the get() returns null, 
>>> rather than throwing an exception.
>>> 
>>> We'd also need to verify whether other context implementations could deal 
>>> with it.
>>> 
>>> Wouldn't that be better :\ ? I can see the point of throwing an exception 
>>> (other than NPE of course), but it feels a little abrupt... particularly 
>>> since seems like previously we've just returned null in such situations.
>> You're right that Cache.get(x) should ideally return null.
>> 
>> InvocationContext.lookupEntry() returning NullCacheEntry and null has a
>> different meaning, though:
>> 
>> * NullCacheEntry means that we are supposed to be able to read that
>> entry (according to readCH) but we haven't found that in DC. This is
>> used for example in CacheLoaderInterceptor, where we skip entries that
>> aren't in the context as opposed to recomputing the hash of the key.
>> * null means that this entry cannot be read on this node because the
>> segment this key belongs to is not in readCH, and therefore the command
>> shouldn't get past distribution interceptor.
>> 
>> I don't mind changing the 'design' as long as it follows some simple
>> rules. I don't see how returning NCE for *any* key could be incorporated
>> into the rules, and how should that behave on multi-key contexts.
>> 
>> In all but distribution mode, during read the key must be always wrapped
>> for read, because there's either no readCH (local) or replicated CH
>> (repl/invalidation). But in invalidation/local mode we can't handle that
>> in distribution interceptor as this is not present.
>> 
>> I would really prefer to see this handled in
>> EntryWrappingInterceptor/EntryWrappingFactory rather than in each
>> command - in #4564 [2] I wanted to narrow the possible situations to be
>> handled in perform(), and other pieces (e.g. return handlers - see
>> dataReadReturnHandler, that will throw NPE as well in TX RR right now).
>> Note that some commands do the check ATM (e.g. functional commands) - I
>> think that those are leftovers and should be gone.
>> 
>> I was about to suggest adding
>> 
>> if (!key.equals(key)) return null;
>> 
>> to all EWI.visitXXX methods as proper implemenations of equals should do the
>> 
>> if (other == this) return true;
>> 
>> anyway as a shortcut, so such check shouldn't affect performance.
>> However, this is not as simple with functional commands which should
>> operate on the null entry (on some node), we have to run these, and you
>> can't even ignore the value, you need some entry in there.
>> 
>> I hate not finding my socks in the drawer where I definitely put those.
>> This just breaks too many things :-(
>> 
>> Btw., it seems that SingleTxContextInvocationContext [1] will fail when
>> the entry is loaded from cache store - this is the place where you could
>> put the entry into invocation context twice. So the use case was
>> somewhat broken before, too.
>> 
>> 
>> [1]
>> https://github.com/infinispan/infinispan/blob/master/core/src/main/java/org/infinispan/context/SingleKeyNonTxInvocationContext.java#L114
>> [2] https://github.com/infinispan/infinispan/pull/4564
>> 
>> 
>>> Cheers,
>>> 
>>>> Radim
>>>> 
>>>>> To be more specific, SingleKeyNonTxInvocationContext.lookupEntry() can 
>>>>> return null, so GetKeyValueCommand should be able to handle it? Or should 
>>>>> SingleKeyNonTxInvocationContext.lookupEntry return 
>>>>> NullCacheEntry.getInstance instead of null?
>>>>> 
>>>>> To provide more specifics, SingleKeyNonTxInvocationContext has 
>>>>> NullCacheEntry.getInstance in cacheEntry variable when it's returning 
>>>>> null. Should it maybe return NullCacheEntry.getInstance instead of null 
>>>>> from lookupEntry() ?
>>>>> 
>>>>> Cheers,
>>>>> 
>>>>>> Radim
>>>>>> 
>>>>>> [3] 
>>>>>> https://github.com/infinispan/infinispan/blob/master/core/src/main/java/org/infinispan/container/EntryFactory.java
>>>>>> 
>>>>>>> I'll create a JIRA to track all issues arising from Hibernate 2LC in a 
>>>>>>> minute, but wanted to get your thoughts firts.
>>>>>>> 
>>>>>>> Cheers,
>>>>>>> 
>>>>>>> [1] https://issues.jboss.org/browse/ISPN-7029
>>>>>>> [2] 
>>>>>>> https://github.com/hibernate/hibernate-orm/blob/master/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/CacheKeysFactoryTest.java#L58
>>>>>>> --
>>>>>>> Galder Zamarreño
>>>>>>> Infinispan, Red Hat
>>>>>>> 
>>>>>> -- 
>>>>>> Radim Vansa <rva...@redhat.com>
>>>>>> JBoss Performance Team
>>>> -- 
>>>> Radim Vansa <rva...@redhat.com>
>>>> JBoss Performance Team
>>>> 
>> 
> 
> 
> -- 
> Radim Vansa <rva...@redhat.com>
> JBoss Performance Team
> 
> _______________________________________________
> 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