[ 
http://jira.magnolia-cms.com/browse/MAGNOLIA-3167?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=27656#action_27656
 ] 

Jan Haderka commented on MAGNOLIA-3167:
---------------------------------------

Actually the reason we synchronize is the related to the fact that we use 
blocking cache by default. If I'm not mistaken the scenario that requires 
synchronization is this:
# Requst A calls {{hasElement()}} which in turn will call {{get(key)}}. Since 
key is not yet in the cache {{get()}} method will return null and place a mutex 
on the key. At which point {{hasElement()}} return false and cache policy will 
return "store". and request will proceed to generate the cache entry
# while the cache entry is being generated, the request B comes for the same 
resource, and the {{hasElement()}} will block in the subsequent call to 
{{cache.get(key)}} (since we use the blocking cache)
# still while the cache entry requested by the A is generated, the request C 
comes and gets stuck in the exactly same place as request B
# now finally, the cache entry have been generated and placed in the cache at 
which point the request A returns.
# since the cache entry have been put in the cache, it will remove the mutex 
and request B will proceed, find the entry in the cache, and will go on with 
the "useCache" behavior.
# unfortunatelly, the reuqest C will be still blocked and will stay that way 
forever since removing the mutex by A released only the first blocked {{get()}} 
call, but all of them. So what applies to C applies to any number of requests 
that come in that very same time window.

The behavior above was a reason why we introduced the synchronization on cache 
in 3.6. I might have explained it in even more details in the user list in the 
past.

Now, considering this issue, the timeout is probably bast solution to avoid 
being locked forever if the thread handling request A gets stuck forever.

As for serving multiple entries from the cache, we should lock on the key 
rather then on the whole cache so only the requests to the cache for given key 
ever gets serialized access as Greg already suggested above. ... Alternatively 
we can drop whole policy/executor based implementation and implement cache in a 
way that would not allow calls to cache to escape ever.



> cache: single blocking request can block all other requests to cached content 
> ------------------------------------------------------------------------------
>
>                 Key: MAGNOLIA-3167
>                 URL: http://jira.magnolia-cms.com/browse/MAGNOLIA-3167
>             Project: Magnolia
>          Issue Type: Bug
>    Affects Versions: 3.6.8, 4.1.4, 4.2.3, 4.3.1
>            Reporter: Philipp Bärfuss
>            Assignee: Boris Kraft
>             Fix For: 4.3.x
>
>
> the cache mechanism can block all requests:
> * cache.get() will block if an other request is caching the same key (this is 
> a feature of the BlockingCache)
>   ** mutex per key kept until cache.put() is called (either with an entry or 
> null value)
> * this code is again in a synchronized block which synchronizes on the cache 
> object itself
>   ** this blocks all other request trying to enter the synchronization block
> The critical scenario which can prevent magnolia from responding any request 
> (all threads blocked) is the following
> 1) first request to a resource which is slow or never returns (request to a 
> service, poor database connection, ..)
> 2) second request to the same resource: --> thread is blocked at 
> EhCacheWrapper.get(key):56, but also keeps the lock on the cache
> 3) all other caching requests are blocked (no matter which url) due to the 
> synchronize block at Default.shouldCache(Cache, AggregationState, 
> FlushPolicy):89
> Solution:
> * don't synchronize on the cache (why are we doing this???)
> * allow configuration of 
> [BlockingCache.timeoutMillis|http://ehcache.org/apidocs/net/sf/ehcache/constructs/blocking/BlockingCache.html#timeoutMillis]
>   ** throw an exception if a request waits for to long
> * uncomment finally block at doFilter(HttpServletRequest, 
> HttpServletResponse, FilterChain), this is a safety net and should log a 
> FATAL ERROR message
>   ** only relevant if the result is a store request

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.magnolia-cms.com/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira



----------------------------------------------------------------
For list details see
http://www.magnolia-cms.com/home/community/mailing-lists.html
To unsubscribe, E-mail to: <dev-list-unsubscr...@magnolia-cms.com>
----------------------------------------------------------------

Reply via email to