Skip to content

Commit ccc8340

Browse files
rvansadreab8
authored andcommitted
HHH-9695 Use non-transactional cache for immutable entities
1 parent 4e2f7ae commit ccc8340

File tree

9 files changed

+112
-71
lines changed

9 files changed

+112
-71
lines changed

hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,6 @@
66
*/
77
package org.hibernate.cache.infinispan;
88

9-
import java.io.FileNotFoundException;
10-
import java.io.IOException;
11-
import java.io.InputStream;
12-
import java.util.ArrayList;
13-
import java.util.Collections;
14-
import java.util.Enumeration;
15-
import java.util.HashMap;
16-
import java.util.HashSet;
17-
import java.util.List;
18-
import java.util.Map;
19-
import java.util.Properties;
20-
import java.util.Set;
21-
import java.util.concurrent.TimeUnit;
22-
239
import org.hibernate.boot.spi.SessionFactoryOptions;
2410
import org.hibernate.cache.CacheException;
2511
import org.hibernate.cache.infinispan.collection.CollectionRegionImpl;
@@ -43,7 +29,6 @@
4329
import org.hibernate.cache.spi.access.AccessType;
4430
import org.hibernate.internal.util.ClassLoaderHelper;
4531
import org.hibernate.internal.util.config.ConfigurationHelper;
46-
4732
import org.infinispan.AdvancedCache;
4833
import org.infinispan.commands.module.ModuleCommandFactory;
4934
import org.infinispan.commons.util.FileLookupFactory;
@@ -61,6 +46,20 @@
6146
import org.infinispan.util.logging.Log;
6247
import org.infinispan.util.logging.LogFactory;
6348

49+
import java.io.FileNotFoundException;
50+
import java.io.IOException;
51+
import java.io.InputStream;
52+
import java.util.ArrayList;
53+
import java.util.Collections;
54+
import java.util.Enumeration;
55+
import java.util.HashMap;
56+
import java.util.HashSet;
57+
import java.util.List;
58+
import java.util.Map;
59+
import java.util.Properties;
60+
import java.util.Set;
61+
import java.util.concurrent.TimeUnit;
62+
6463
/**
6564
* A {@link RegionFactory} for <a href="http://www.jboss.org/infinispan">Infinispan</a>-backed cache
6665
* regions.
@@ -133,6 +132,13 @@ public class InfinispanRegionFactory implements RegionFactory {
133132
*/
134133
public static final String ENTITY_CACHE_RESOURCE_PROP = PREFIX + ENTITY_KEY + CONFIG_SUFFIX;
135134

135+
private static final String IMMUTABLE_ENTITY_KEY = "immutable-entity";
136+
137+
/**
138+
* Name of the configuration that should be used for immutable entity caches.
139+
*/
140+
public static final String IMMUTABLE_ENTITY_CACHE_RESOURCE_PROP = PREFIX + IMMUTABLE_ENTITY_KEY + CONFIG_SUFFIX;
141+
136142
private static final String COLLECTION_KEY = "collection";
137143

138144
/**
@@ -175,6 +181,11 @@ public class InfinispanRegionFactory implements RegionFactory {
175181
*/
176182
public static final String DEF_ENTITY_RESOURCE = "entity";
177183

184+
/**
185+
* Default value for {@link #IMMUTABLE_ENTITY_CACHE_RESOURCE_PROP}.
186+
*/
187+
public static final String DEF_IMMUTABLE_ENTITY_RESOURCE = "immutable-entity";
188+
178189
/**
179190
* Default value for {@link #TIMESTAMPS_CACHE_RESOURCE_PROP}.
180191
*/
@@ -238,9 +249,9 @@ public CollectionRegion buildCollectionRegion(
238249
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
239250
throws CacheException {
240251
if ( log.isDebugEnabled() ) {
241-
log.debug( "Building entity cache region [" + regionName + "]" );
252+
log.debugf( "Building entity cache region [%s] (mutable=%s, versioned=%s)", regionName, metadata.isMutable(), metadata.isVersioned());
242253
}
243-
final AdvancedCache cache = getCache( regionName, ENTITY_KEY, properties );
254+
final AdvancedCache cache = getCache( regionName, metadata.isMutable() ? ENTITY_KEY : IMMUTABLE_ENTITY_KEY, properties );
244255
final EntityRegionImpl region = new EntityRegionImpl( cache, regionName, metadata, this );
245256
startRegion( region, regionName );
246257
return region;
@@ -446,8 +457,11 @@ private void startRegion(BaseRegion region, String regionName) {
446457

447458
private Map<String, TypeOverrides> initGenericDataTypeOverrides() {
448459
final TypeOverrides entityOverrides = new TypeOverrides();
449-
entityOverrides.setCacheName( DEF_ENTITY_RESOURCE );
460+
entityOverrides.setCacheName(DEF_ENTITY_RESOURCE);
450461
typeOverrides.put( ENTITY_KEY, entityOverrides );
462+
final TypeOverrides immutableEntityOverrides = new TypeOverrides();
463+
immutableEntityOverrides.setCacheName( DEF_IMMUTABLE_ENTITY_RESOURCE );
464+
typeOverrides.put( IMMUTABLE_ENTITY_KEY, immutableEntityOverrides );
451465
final TypeOverrides collectionOverrides = new TypeOverrides();
452466
collectionOverrides.setCacheName( DEF_ENTITY_RESOURCE );
453467
typeOverrides.put( COLLECTION_KEY, collectionOverrides );
@@ -509,7 +523,7 @@ private TypeOverrides getOrCreateConfig(int prefixLoc, String key, int suffixLoc
509523
}
510524

511525
private void defineGenericDataTypeCacheConfigurations(Properties properties) {
512-
final String[] defaultGenericDataTypes = new String[] {ENTITY_KEY, COLLECTION_KEY, TIMESTAMPS_KEY, QUERY_KEY};
526+
final String[] defaultGenericDataTypes = new String[] {ENTITY_KEY, IMMUTABLE_ENTITY_KEY, COLLECTION_KEY, TIMESTAMPS_KEY, QUERY_KEY};
513527
for ( String type : defaultGenericDataTypes ) {
514528
final TypeOverrides override = overrideStatisticsIfPresent( typeOverrides.get( type ), properties );
515529
final String cacheName = override.getCacheName();

hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/TypeOverrides.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
*/
77
package org.hibernate.cache.infinispan;
88

9-
import java.util.HashSet;
10-
import java.util.Locale;
11-
import java.util.Set;
12-
139
import org.hibernate.cache.CacheException;
14-
1510
import org.infinispan.configuration.cache.Configuration;
1611
import org.infinispan.configuration.cache.ConfigurationBuilder;
1712
import org.infinispan.eviction.EvictionStrategy;
1813

14+
import java.io.Serializable;
15+
import java.util.HashSet;
16+
import java.util.Locale;
17+
import java.util.Set;
18+
1919
/**
2020
* This class represents Infinispan cache parameters that can be configured via hibernate configuration properties
2121
* for either general entity/collection/query/timestamp data type caches and overrides for individual entity or
@@ -24,7 +24,7 @@
2424
* @author Galder Zamarreño
2525
* @since 3.5
2626
*/
27-
public class TypeOverrides {
27+
public class TypeOverrides implements Serializable {
2828

2929
private final Set<String> overridden = new HashSet<String>();
3030

hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/EntityRegionImpl.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) thr
4646
case READ_ONLY:
4747
return new ReadOnlyAccess( this );
4848
case TRANSACTIONAL:
49-
return new TransactionalAccess( this );
49+
if (getCacheDataDescription().isMutable()) {
50+
return new TransactionalAccess(this);
51+
} else {
52+
return new ReadOnlyAccess(this);
53+
}
5054
default:
5155
throw new CacheException( "Unsupported access type [" + accessType.getExternalName() + "]" );
5256
}

hibernate-infinispan/src/main/resources/org/hibernate/cache/infinispan/builder/infinispan-configs.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626
<expiration max-idle="100000" interval="5000"/>
2727
</invalidation-cache>
2828

29+
<!-- Default configuration for immutable entities -->
30+
<invalidation-cache name="immutable-entity" mode="SYNC" remote-timeout="20000">
31+
<locking isolation="READ_COMMITTED" concurrency-level="1000" acquire-timeout="15000" striping="false"/>
32+
<transaction mode="NONE"/>
33+
<eviction max-entries="10000" strategy="LRU"/>
34+
<expiration max-idle="100000" interval="5000"/>
35+
</invalidation-cache>
36+
2937
<!-- Default configuration is appropriate for entity/collection caching. -->
3038
<invalidation-cache name="entity-repeatable" mode="SYNC" remote-timeout="20000">
3139
<locking isolation="REPEATABLE_READ" concurrency-level="1000" acquire-timeout="15000" striping="false"/>

hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
*/
77
package org.hibernate.test.cache.infinispan;
88

9-
import java.util.Properties;
10-
import javax.transaction.TransactionManager;
11-
129
import org.hibernate.boot.spi.SessionFactoryOptions;
1310
import org.hibernate.cache.CacheException;
1411
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
@@ -17,14 +14,13 @@
1714
import org.hibernate.cache.infinispan.query.QueryResultsRegionImpl;
1815
import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
1916
import org.hibernate.cache.infinispan.tm.HibernateTransactionManagerLookup;
17+
import org.hibernate.cache.internal.CacheDataDescriptionImpl;
18+
import org.hibernate.cache.spi.CacheDataDescription;
2019
import org.hibernate.cfg.Environment;
2120
import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;
2221
import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform;
23-
24-
import org.hibernate.testing.ServiceRegistryBuilder;
2522
import org.hibernate.test.cache.infinispan.functional.SingleNodeTestCase;
26-
import org.junit.Test;
27-
23+
import org.hibernate.testing.ServiceRegistryBuilder;
2824
import org.infinispan.AdvancedCache;
2925
import org.infinispan.configuration.cache.CacheMode;
3026
import org.infinispan.configuration.cache.Configuration;
@@ -34,13 +30,13 @@
3430
import org.infinispan.manager.DefaultCacheManager;
3531
import org.infinispan.manager.EmbeddedCacheManager;
3632
import org.infinispan.test.TestingUtil;
33+
import org.infinispan.transaction.TransactionMode;
34+
import org.junit.Test;
35+
36+
import javax.transaction.TransactionManager;
37+
import java.util.Properties;
3738

38-
import static org.junit.Assert.assertEquals;
39-
import static org.junit.Assert.assertFalse;
40-
import static org.junit.Assert.assertNotNull;
41-
import static org.junit.Assert.assertNull;
42-
import static org.junit.Assert.assertTrue;
43-
import static org.junit.Assert.fail;
39+
import static org.junit.Assert.*;
4440

4541
/**
4642
* InfinispanRegionFactoryTestCase.
@@ -49,6 +45,8 @@
4945
* @since 3.5
5046
*/
5147
public class InfinispanRegionFactoryTestCase {
48+
private static CacheDataDescription MUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(true, false, null);
49+
private static CacheDataDescription IMMUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(false, false, null);
5250

5351
@Test
5452
public void testConfigurationProcessing() {
@@ -136,7 +134,7 @@ public void testBuildEntityCollectionRegionsPersonPlusEntityCollectionOverrides(
136134
assertFalse(factory.getDefinedConfigurations().contains(addresses));
137135
AdvancedCache cache;
138136

139-
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion(person, p, null);
137+
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion(person, p, MUTABLE_NON_VERSIONED);
140138
assertNotNull(factory.getTypeOverrides().get(person));
141139
assertTrue(factory.getDefinedConfigurations().contains(person));
142140
assertNull(factory.getTypeOverrides().get(address));
@@ -149,7 +147,7 @@ public void testBuildEntityCollectionRegionsPersonPlusEntityCollectionOverrides(
149147
assertEquals(30000, cacheCfg.expiration().maxIdle());
150148
assertFalse(cacheCfg.jmxStatistics().enabled());
151149

152-
region = (EntityRegionImpl) factory.buildEntityRegion(address, p, null);
150+
region = (EntityRegionImpl) factory.buildEntityRegion(address, p, MUTABLE_NON_VERSIONED);
153151
assertNotNull(factory.getTypeOverrides().get(person));
154152
assertTrue(factory.getDefinedConfigurations().contains(person));
155153
assertNull(factory.getTypeOverrides().get(address));
@@ -160,7 +158,7 @@ public void testBuildEntityCollectionRegionsPersonPlusEntityCollectionOverrides(
160158
assertEquals(20000, cacheCfg.eviction().maxEntries());
161159
assertFalse(cacheCfg.jmxStatistics().enabled());
162160

163-
region = (EntityRegionImpl) factory.buildEntityRegion(car, p, null);
161+
region = (EntityRegionImpl) factory.buildEntityRegion(car, p, MUTABLE_NON_VERSIONED);
164162
assertNotNull(factory.getTypeOverrides().get(person));
165163
assertTrue(factory.getDefinedConfigurations().contains(person));
166164
assertNull(factory.getTypeOverrides().get(address));
@@ -172,7 +170,7 @@ public void testBuildEntityCollectionRegionsPersonPlusEntityCollectionOverrides(
172170
assertFalse(cacheCfg.jmxStatistics().enabled());
173171

174172
CollectionRegionImpl collectionRegion = (CollectionRegionImpl)
175-
factory.buildCollectionRegion(addresses, p, null);
173+
factory.buildCollectionRegion(addresses, p, MUTABLE_NON_VERSIONED);
176174
assertNotNull(factory.getTypeOverrides().get(addresses));
177175
assertTrue(factory.getDefinedConfigurations().contains(person));
178176
assertNull(factory.getTypeOverrides().get(parts));
@@ -185,7 +183,7 @@ public void testBuildEntityCollectionRegionsPersonPlusEntityCollectionOverrides(
185183
assertEquals(35000, cacheCfg.expiration().maxIdle());
186184
assertFalse(cacheCfg.jmxStatistics().enabled());
187185

188-
collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion(parts, p, null);
186+
collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion(parts, p, MUTABLE_NON_VERSIONED);
189187
assertNotNull(factory.getTypeOverrides().get(addresses));
190188
assertTrue(factory.getDefinedConfigurations().contains(addresses));
191189
assertNull(factory.getTypeOverrides().get(parts));
@@ -196,7 +194,7 @@ public void testBuildEntityCollectionRegionsPersonPlusEntityCollectionOverrides(
196194
assertEquals(25000, cacheCfg.eviction().maxEntries());
197195
assertFalse(cacheCfg.jmxStatistics().enabled());
198196

199-
collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion(parts, p, null);
197+
collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion(parts, p, MUTABLE_NON_VERSIONED);
200198
assertNotNull(factory.getTypeOverrides().get(addresses));
201199
assertTrue(factory.getDefinedConfigurations().contains(addresses));
202200
assertNull(factory.getTypeOverrides().get(parts));
@@ -224,7 +222,7 @@ public void testBuildEntityCollectionRegionOverridesOnly() {
224222
InfinispanRegionFactory factory = createRegionFactory(p);
225223
try {
226224
factory.getCacheManager();
227-
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, null);
225+
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, MUTABLE_NON_VERSIONED);
228226
assertNull(factory.getTypeOverrides().get("com.acme.Address"));
229227
cache = region.getCache();
230228
Configuration cacheCfg = cache.getCacheConfiguration();
@@ -235,7 +233,7 @@ public void testBuildEntityCollectionRegionOverridesOnly() {
235233
assertEquals(100000, cacheCfg.expiration().maxIdle());
236234

237235
CollectionRegionImpl collectionRegion = (CollectionRegionImpl)
238-
factory.buildCollectionRegion("com.acme.Person.addresses", p, null);
236+
factory.buildCollectionRegion("com.acme.Person.addresses", p, MUTABLE_NON_VERSIONED);
239237
assertNull(factory.getTypeOverrides().get("com.acme.Person.addresses"));
240238
cache = collectionRegion.getCache();
241239
cacheCfg = cache.getCacheConfiguration();
@@ -264,7 +262,7 @@ public void testBuildEntityRegionPersonPlusEntityOverridesWithoutCfg() {
264262
factory.getCacheManager();
265263
assertNotNull(factory.getTypeOverrides().get(person));
266264
assertFalse(factory.getDefinedConfigurations().contains(person));
267-
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion(person, p, null);
265+
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion(person, p, MUTABLE_NON_VERSIONED);
268266
assertNotNull(factory.getTypeOverrides().get(person));
269267
assertTrue(factory.getDefinedConfigurations().contains(person));
270268
AdvancedCache cache = region.getCache();
@@ -279,6 +277,23 @@ public void testBuildEntityRegionPersonPlusEntityOverridesWithoutCfg() {
279277
}
280278
}
281279

280+
@Test
281+
public void testBuildImmutableEntityRegion() {
282+
AdvancedCache cache;
283+
Properties p = new Properties();
284+
InfinispanRegionFactory factory = createRegionFactory(p);
285+
try {
286+
factory.getCacheManager();
287+
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, IMMUTABLE_NON_VERSIONED);
288+
assertNull(factory.getTypeOverrides().get("com.acme.Address"));
289+
cache = region.getCache();
290+
Configuration cacheCfg = cache.getCacheConfiguration();
291+
assertEquals("Immutable entity should get non-transactional cache", TransactionMode.NON_TRANSACTIONAL, cacheCfg.transaction().transactionMode());
292+
} finally {
293+
factory.stop();
294+
}
295+
}
296+
282297
@Test(expected = CacheException.class)
283298
public void testTimestampValidation() {
284299
Properties p = createProperties();
@@ -448,12 +463,12 @@ public void testEnableStatistics() {
448463
try {
449464
EmbeddedCacheManager manager = factory.getCacheManager();
450465
assertTrue(manager.getCacheManagerConfiguration().globalJmxStatistics().enabled());
451-
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, null);
466+
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, MUTABLE_NON_VERSIONED);
452467
AdvancedCache cache = region.getCache();
453468
assertTrue(factory.getTypeOverrides().get("entity").isExposeStatistics());
454469
assertTrue(cache.getCacheConfiguration().jmxStatistics().enabled());
455470

456-
region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Person", p, null);
471+
region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Person", p, MUTABLE_NON_VERSIONED);
457472
cache = region.getCache();
458473
assertTrue(factory.getTypeOverrides().get("com.acme.Person").isExposeStatistics());
459474
assertTrue(cache.getCacheConfiguration().jmxStatistics().enabled());
@@ -476,7 +491,7 @@ public void testEnableStatistics() {
476491
assertTrue(cache.getCacheConfiguration().jmxStatistics().enabled());
477492

478493
CollectionRegionImpl collectionRegion = (CollectionRegionImpl)
479-
factory.buildCollectionRegion("com.acme.Person.addresses", p, null);
494+
factory.buildCollectionRegion("com.acme.Person.addresses", p, MUTABLE_NON_VERSIONED);
480495
cache = collectionRegion.getCache();
481496
assertTrue(factory.getTypeOverrides().get("collection").isExposeStatistics());
482497
assertTrue(cache.getCacheConfiguration().jmxStatistics().enabled());
@@ -497,12 +512,12 @@ public void testDisableStatistics() {
497512
p.setProperty("hibernate.cache.infinispan.entity.eviction.max_entries", "10000");
498513
InfinispanRegionFactory factory = createRegionFactory(p);
499514
try {
500-
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, null);
515+
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, MUTABLE_NON_VERSIONED);
501516
AdvancedCache cache = region.getCache();
502517
assertFalse(factory.getTypeOverrides().get("entity").isExposeStatistics());
503518
assertFalse(cache.getCacheConfiguration().jmxStatistics().enabled());
504519

505-
region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Person", p, null);
520+
region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Person", p, MUTABLE_NON_VERSIONED);
506521
cache = region.getCache();
507522
assertFalse(factory.getTypeOverrides().get("com.acme.Person").isExposeStatistics());
508523
assertFalse(cache.getCacheConfiguration().jmxStatistics().enabled());
@@ -524,7 +539,7 @@ public void testDisableStatistics() {
524539
assertFalse(cache.getCacheConfiguration().jmxStatistics().enabled());
525540

526541
CollectionRegionImpl collectionRegion = (CollectionRegionImpl)
527-
factory.buildCollectionRegion("com.acme.Person.addresses", p, null);
542+
factory.buildCollectionRegion("com.acme.Person.addresses", p, MUTABLE_NON_VERSIONED);
528543
cache = collectionRegion.getCache();
529544
assertFalse(factory.getTypeOverrides().get("collection").isExposeStatistics());
530545
assertFalse(cache.getCacheConfiguration().jmxStatistics().enabled());

0 commit comments

Comments
 (0)