Thanks for the reply Jan. Took me several reads, think I understand now.
I'll check the docco on ehcache.

2009/10/16 Jan Haderka <[email protected]>

>
> It's been a while, so bear with me.
> I guess the comment should have read BlockingCache or even better the
> net.st.ehcache.construct.blockingBlockingCache
>
> As you have noticed Magnolia uses EhCache underneath. The EhCache
> provides 2 implementations of EhCache interface, one of which is
> blocking (in a sense that after first call to cache.get() it will block
> all consecutive calls until there is something to return from the cache.
> Since there might be multiple threads calling different instances of the
> Default class we need to prevent such thing from happening to avoid a
> dead lock. What happens is that the first thread enters the method,
> calls the hasElement() (which results in call to cache.get()), if the
> key is not cached (the potential collision situation), the hasElement()
> returns false and new CachePolicyResult (with request to store the key)
> is created. If this thread finishes storing the key before next request
> comes, everything is fine.
> Let's assume the second request for same key comes _before_ the key is
> stored, it will enter the synchronized block (because the first thread
> already left it) and it will call the hasElement() (and consecutive call
> to cache.get() will block the thread there in the synchronized block
> until the cache key is stored and retrievable). So this second thread is
> effectively stuck in the sync block, preventing anyone else from
> entering it until the first thread is done with the retrieval of the
> content for the key and caching the entry.
> The point here is that we know exactly how many other threads might have
> called the cache.get() method and can recover them by placing the value
> later in the executor.Store.processCacheRequest() method (in the finally
> block, notice we store the the cache key anyway, even if we can't
> generate the entry to release the second thread that might be stuck in
> the synchronized block in the Default cache policy). This works for as
> long as there is max one thread stuck in the hasElement() (or more
> precisely in cache.get()) call. If there will be more requests for the
> key, they would be all released at a same time and they will all try to
> generate the entry at a same time. This in itself should not be the
> problem, but you need to keep in mind that entry creation is normally
> pretty fast. If this situation occurred in the first place, it was
> because either server is very busy, or producing response for this given
> request is very heavy and slow. In either case you don't want to perform
> it multiple times in parallel as it will not be faster then waiting for
> the one processing thread to finish it and provide it as cached entry to
> the others.
>
> Hope this was clear enough.
>
> More pointers - look at the svn history of the Default cache policy.
> Look at the issues related to cache since Magnolia 3.6 (incl. the
> milestone and RC issues).
> Look at the EhCacheWrapper, Store executor and CacheFilter. Look at the
> EhCache documentation and explanation of BlockingCache.
>
>
> Cheers,
> Jan
>
>
> On Thu, 2009-10-08 at 15:55 +0100, Luke Biddell wrote:
> >
> > Hi folks,
> >
> > I've got some questions about the cache and hoped you wouldn't mind me
> > harassing you about it. I've some queries around the cache
> > implementation within Magnolia and was hoping you could set me
> > straight.
> >
> >
> > I've recently implemented a custom cache policy and as part of that
> > work stumbled upon this piece of code within the
> > info.magnolia.module.cache.cachepolicy.Default class.
> >
> >
> > // we need to synchronize on the cache instance, as multiple threads
> > might be accessing this
> > // concurrently, and we don't want to block the system if we're using
> > a blocking cache.
> > // (since hasElement() might place a mutex on the cache key)
> > synchronized (cache) {
> >     if (cache.hasElement(key)) {
> >         final Object cachedEntry = cache.get(key);
> >         return new CachePolicyResult(CachePolicyResult.useCache, key,
> > cachedEntry);
> >     } else {
> >         return new CachePolicyResult(CachePolicyResult.store, key,
> > null);
> >     }
> > }
> >
> >
> >
> >
> >
> >
> > 1) My first query is around the two calls to retrieve any given
> > element. eg you first call hasElement and then get. Could we not just
> > call get and check null as below?
> >
> >
> >
> >
> >
> >
> > final Object cachedEntry = cache.get(key);
> > if (cachedEntry != null) {
> >       return new CachePolicyResult(CachePolicyResult.useCache, key,
> > cachedEntry);
> > } else {
> >       return new CachePolicyResult(CachePolicyResult.store, key,
> > null);
> > }
> >
> >
> >
> > 2) The second query I have is about the use of the synchronised block
> > around the cache retrieval. I've searched the entire codebase and all
> > of the calls which add to the cache have no such synchronized block,
> > only the retrieval does (I could easily have missed them though as I
> > don't have the full source).
> >
> > The comment above the block doesn't make sense as by synchronising on
> > the cache object you're only marshalling access to that section of
> > code; subsequent calls to hasElement and get will block globally
> > regardless of this?
> >
> > Under the covers, it appears to be using ehCache which is fully thread
> > safe and no doubt uses appropriate read/write locking.
> >
> > I would also expect locking code to be encapsulated within the cache
> > class implementation, the code which uses the cache can then be
> > properly agnostic regarding the locking strategy.
> >
> > Thanks for any pointers you can give.
> >
> >
> >
> > Luke
>
>
> ----------------------------------------------------------------
> For list details see
> http://www.magnolia-cms.com/home/community/mailing-lists.html
> To unsubscribe, E-mail to: <[email protected]>
> ----------------------------------------------------------------
>
>

----------------------------------------------------------------
For list details see
http://www.magnolia-cms.com/home/community/mailing-lists.html
To unsubscribe, E-mail to: <[email protected]>
----------------------------------------------------------------

Reply via email to