Race condition in building query cache
--------------------------------------
Key: HHH-5945
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5945
Project: Hibernate Core
Issue Type: Bug
Components: caching (L2)
Affects Versions: 3.6.1
Environment: Hibernate 3.6.1, EhCache 2.3.0..2.3.2, MSSQL 2005 Developer Edition
Reporter: Luca Domenichini
I have this sample program that creates 10 threads that executes the same cached query in
a thread-local current session context. Entity ClasseAltezza is a READ_ONLY cached
entity.
{panel}{noformat}
public static void main(String[] args) {
List<Thread> threads = new ArrayList<Thread>();
for (int i=0; i<10; i++) {
Thread t = new Thread() {
@Override
public void run() {
try {
HibernateUtil.beginTransaction();
HibernateUtil.getCurrentSession()
.createCriteria(ClasseAltezza.class)
.setCacheable(true)
.setCacheRegion(ClasseAltezza.class.toString())
.list();
HibernateUtil.commitTransaction();
}
catch (Exception ex) {
ex.printStackTrace();
HibernateUtil.rollbackTransaction();
}
}
};
threads.add(t);
}
for (Thread t : threads)
t.start();
}
{noformat}{panel}
This is the output:
{panel}{noformat}org.hibernate.cache.CacheException: net.sf.ehcache.ObjectExistsException:
Cache class com.promag.wms.base.persistence.entities.ClasseAltezza already exists
at org.hibernate.cache.EhCacheProvider.buildCache(EhCacheProvider.java:101)
at
org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge.buildQueryResultsRegion(RegionFactoryCacheProviderBridge.java:115)
at org.hibernate.cache.StandardQueryCache.<init>(StandardQueryCache.java:78)
at
org.hibernate.cache.StandardQueryCacheFactory.getQueryCache(StandardQueryCacheFactory.java:44)
at org.hibernate.impl.SessionFactoryImpl.getQueryCache(SessionFactoryImpl.java:1173)
at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2285)
at org.hibernate.loader.Loader.list(Loader.java:2268)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)
at
com.promag.wms.base.persistence.methods.ClasseAltezzaMethods.getAll(ClasseAltezzaMethods.java:30)
at Test$1.run(Test.java:20)
Caused by: net.sf.ehcache.ObjectExistsException: Cache class
com.promag.wms.base.persistence.entities.ClasseAltezza already exists
at net.sf.ehcache.CacheManager.addCache(CacheManager.java:888)
at org.hibernate.cache.EhCacheProvider.buildCache(EhCacheProvider.java:94)
... 11 more
{noformat}{panel}
I see that in Hibernate 3.6.0 there were a synchronized block in method
SessionFactory.getQueryCache(String regionName) the prevented the same query region to be
built twice as it happens in Hibernate 3.6.1, were the synchronized block is missing..
This is the method in SessionFactoryImpl:
{panel}{noformat}
public QueryCache getQueryCache(String regionName) throws HibernateException {
if ( regionName == null ) {
return getQueryCache();
}
if ( !settings.isQueryCacheEnabled() ) {
return null;
}
synchronized ( allCacheRegions ) { // THIS SYNCHRONIZED IS MISSING IN 3.6.1!!!!
QueryCache currentQueryCache = ( QueryCache ) queryCaches.get( regionName );
if ( currentQueryCache == null ) {
currentQueryCache = settings.getQueryCacheFactory().getQueryCache( regionName,
updateTimestampsCache, settings, properties );
queryCaches.put( regionName, currentQueryCache );
allCacheRegions.put( currentQueryCache.getRegion().getName(),
currentQueryCache.getRegion() );
}
return currentQueryCache;
}
}
{noformat}{panel}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira