[hibernate-dev] Re: HSEARCH-178

Emmanuel Bernard emmanuel at hibernate.org
Tue Apr 14 12:09:51 EDT 2009

On  Apr 14, 2009, at 16:22, Sanne Grinovero wrote:

> I'm going for the Map approach, to favor cleaner code and because you
> appear to be more comfortable with it.
> Even so there are two more points to consider:
> 1)If in the future a code change of the Synchronization (stored in the
> WeakMap as a value)
> would be changed in any way to get a (hard) reference to the session,
> we'll get a memory leak, as in HSEARCH-314.
> As much as the threadlocal is dangerous, we have to be carefull with
> the WeakMap.

Yes I know. Ideally we would add that to the Synchornize JavaDoc,  
except we can't :)
Add a warning to PostTransactionWorkQueueSynchronization and  

> 2)Performance: you are reminding this is just a workaround for people
> which don't like transactions, but the flushlistener is registered for
> everybody.
> So nothing will be put in the map (skipping the Synchronization  
> registration) in
> a correct usage case, but still during the flushlistener I've to  
> look into
> the map to verify there's nothing to do.
> I'm not worried about the performance impact of looking into an  
> empty map,
> but felt I had to keep you informed.

I guess we could add a volatile flag marking the activation but i  
don't think it is worth the effort.

> 2009/4/14 Emmanuel Bernard <emmanuel at hibernate.org>:
>> On  Apr 14, 2009, at 13:03, Sanne Grinovero wrote:
>>> I've 2 inline answers:
>>> 2009/4/14 Emmanuel Bernard <emmanuel at hibernate.org>:
>>>> Read inline
>>>> On  Apr 13, 2009, at 17:22, Sanne Grinovero wrote:
>>>>> After our chat about the topic I thought that I only needed some  
>>>>> minor
>>>>> changes,
>>>>> was quite wrong.
>>>>> I moved the flush listener to the usual  
>>>>> FullTextIndexEventListener,
>>>>> using
>>>>> delegation at first as we had agreed. This got me into troubles  
>>>>> with
>>>>> the Serialization test of the FullTextEntityManager, I had to  
>>>>> adapt
>>>>> EventSourceTransactionContext changing a field to transient and
>>>>> having the code manage the case in which the values are lost by
>>>>> deserialization.
>>>>> After this I removed the delegation moving the code to the
>>>>> FullTextIndexEventListener
>>>>> which resulted in simpler code.
>>>>> You made me think about what was happening in case of an error  
>>>>> during
>>>>> the flush processing in the default listener, so I've replaced  
>>>>> the Map
>>>>> with a combination
>>>>> of non-static ThreadLocal with a weak reference to the flushing  
>>>>> Session,
>>>>> which is checked for == identity to make sure the synch is  
>>>>> relevant to
>>>>> the same session,
>>>>> in case of a previously not cleaned-up flush by the same Thread  
>>>>> (as in
>>>>> a Map, but I only need
>>>>> the last stored value for the current session, and only for the  
>>>>> same
>>>>> thread).
>>>> I think I don't like the ThreadLocal approach. What is your  
>>>> reasoning for
>>>> using a thread local variable? What would make it less compelling  
>>>> if we
>>>> were
>>>> not using a TL?
>>> the two event listeners "on-post-somethingchanged" and "flush" are
>>> executed
>>> one after the other right away, atomically from a out-of-hibernate- 
>>> search
>>> point
>>> of view. In the test code if I put breakpoints in both the "register
>>> synch" routing
>>> and "find the synch from the flushlistener" thay both happen only  
>>> when
>>> the client code is asking to flush.
>>> This made me think the two routines are always being called by the  
>>> same
>>> thread,
>>> and there is no chance to begin doing something else between the  
>>> first
>>> operation
>>> and the second operation: it's not possible that, for example, the  
>>> Session
>>> is
>>> passivated or suspendend (thinking about long running  
>>> conversations).
>>> The only way to stop the second to happen is having
>>> an exception in the default hibernate flush listener: that's the
>>> reason for the weak
>>> reference to Session.
>>> These thoughts leaded me to think that a concurrent map is overkill,
>>> especially
>>> considering that every thread in the application is to access
>>> this map twice per flush: to put in an object, and get it back
>>> immediately after that,
>>> and no thread trying to say anything to the others or wanting to  
>>> store
>>> it for a longer
>>> time. So I thought the ThreadLocal was the natural answer.
>>> Still the resulting code is ugly, I'm happy to forget my performance
>>> thoughts if we
>>> could get with a cleaner solution.
>>> I've another version ready using a WeakIdentityHashMap, it's also
>>> passing the tests,
>>> and is a bit more readable, but I'm unsure about which is better.
>>> Shall I commit the one using WeakIdentityHashMap instead of  
>>> ThreadLocal?
>> I looked that the TL impl in Java SE and they are hosted on a per  
>> Thread
>> object basis, so I guess there is no concurrency lock here. So it  
>> all boils
>> down to which is faster:
>>  - a concurrent map look up access
>>  - getting the current Thread object + a map lookup (internal TL  
>> variable
>> impl)
>> Up to you. I have the tendency to limit my TL use as it has caused  
>> issues in
>> the past.
>> Remember this part of the code is used only as a workaround for  
>> people
>> misconfiguring HSearch so I am not too fussed about the perf.

More information about the hibernate-dev mailing list