[hibernate-commits] Hibernate SVN: r17355 - in core/branches/INFINISPAN/cache-infinispan/src: main/java/org/hibernate/cache/infinispan/collection and 13 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Tue Aug 18 15:48:57 EDT 2009
Author: galder.zamarreno at jboss.com
Date: 2009-08-18 15:48:57 -0400 (Tue, 18 Aug 2009)
New Revision: 17355
Added:
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java
Removed:
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanConfiguration.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TimestampTypeOverrides.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractInfinispanTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/util/
Modified:
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/InfinispanCollectionRegion.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/InfinispanEntityRegion.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/InfinispanQueryResultsRegion.java
core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/InfinispanTimestampsRegion.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java
core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java
Log:
[ISPN-6] Infinispan now uses Hibernate's transaction manager.
Deleted: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanConfiguration.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanConfiguration.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanConfiguration.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,39 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.hibernate.cache.infinispan;
-
-import org.infinispan.config.Configuration;
-
-/**
- * InfinispanConfiguration.
- *
- * @author Galder Zamarreño
- * @since 4.0
- */
-public class InfinispanConfiguration {
-
- private final Configuration configuration;
-
- public InfinispanConfiguration(Configuration configuration) {
- this.configuration = configuration;
- }
-}
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -9,6 +9,8 @@
import java.util.Properties;
import java.util.Set;
+import javax.transaction.TransactionManager;
+
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CollectionRegion;
@@ -20,7 +22,10 @@
import org.hibernate.cache.infinispan.entity.InfinispanEntityRegion;
import org.hibernate.cache.infinispan.query.InfinispanQueryResultsRegion;
import org.hibernate.cache.infinispan.timestamp.InfinispanTimestampsRegion;
+import org.hibernate.cache.infinispan.timestamp.TimestampTypeOverrides;
+import org.hibernate.cache.infinispan.tm.HibernateTransactionManagerLookup;
import org.hibernate.cfg.Settings;
+import org.hibernate.transaction.TransactionManagerLookup;
import org.hibernate.util.PropertiesHelper;
import org.infinispan.Cache;
import org.infinispan.config.Configuration;
@@ -126,6 +131,10 @@
private final Map<String, TypeOverrides> typeOverrides = new HashMap<String, TypeOverrides>();
private final Set<String> definedConfigurations = new HashSet<String>();
+
+ private org.infinispan.transaction.lookup.TransactionManagerLookup transactionManagerlookup;
+
+ private TransactionManager transactionManager;
/**
* Create a new instance using the default configuration.
@@ -143,46 +152,17 @@
}
/** {@inheritDoc} */
- public CollectionRegion buildCollectionRegion(String regionName, Properties properties,
- CacheDataDescription metadata) throws CacheException {
+ public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException {
log.debug("Building collection cache region [" + regionName + "]");
- Cache cache = getCache(regionName, COLLECTION_KEY);
- return new InfinispanCollectionRegion(cache, regionName, metadata);
+ Cache cache = getCache(regionName, COLLECTION_KEY, properties);
+ return new InfinispanCollectionRegion(cache, regionName, metadata, transactionManager);
}
/** {@inheritDoc} */
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException {
if (log.isDebugEnabled()) log.debug("Building entity cache region [" + regionName + "]");
- Cache cache = getCache(regionName, ENTITY_KEY);
- return new InfinispanEntityRegion(cache, regionName, metadata);
-// TypeOverrides regionOverride = typeOverrides.get(regionName);
-// if (regionOverride != null) {
-// if (log.isDebugEnabled()) log.debug("Entity cache region specific configuration exists: " + regionOverride);
-// String cacheName = regionOverride.getCacheName();
-// String templateCacheName = null;
-// if (cacheName != null) {
-// // If override has been converted to cache configuration, it means that the cache configuration has
-// // already been defined and hence we only need to get the cache instance corresponding to that cache name
-// if (!regionOverride.isConvertedToInfinispanConfiguration()) {
-// templateCacheName = cacheName;
-// Configuration regionCacheCfg = regionOverride.createInfinispanConfiguration();
-// manager.defineConfiguration(cacheName, templateCacheName, regionCacheCfg);
-// }
-// cache = manager.getCache(cacheName);
-// } else {
-// // If cache name is null, the base configuration is the generic entity data type one
-// // and the cache name is the name of the region.
-// if (!regionOverride.isConvertedToInfinispanConfiguration()) {
-// templateCacheName = typeOverrides.get(ENTITY_KEY).getCacheName();
-// Configuration regionCacheCfg = regionOverride.createInfinispanConfiguration();
-// manager.defineConfiguration(regionName, templateCacheName, regionCacheCfg);
-// }
-// cache = manager.getCache(regionName);
-// }
-// } else {
-// // No region specific overrides, get a cache instance for the generic entity data type region
-// cache = manager.getCache(typeOverrides.get(ENTITY_KEY).getCacheName());
-// }
+ Cache cache = getCache(regionName, ENTITY_KEY, properties);
+ return new InfinispanEntityRegion(cache, regionName, metadata, transactionManager);
}
/**
@@ -192,7 +172,7 @@
throws CacheException {
log.debug("Building query results cache region [" + regionName + "]");
String cacheName = typeOverrides.get(QUERY_KEY).getCacheName();
- return new InfinispanQueryResultsRegion(manager.getCache(cacheName), regionName);
+ return new InfinispanQueryResultsRegion(manager.getCache(cacheName), regionName, properties, transactionManager);
}
/**
@@ -202,7 +182,7 @@
throws CacheException {
log.debug("Building timestamps cache region [" + regionName + "]");
String cacheName = typeOverrides.get(TIMESTAMPS_KEY).getCacheName();
- return new InfinispanTimestampsRegion(manager.getCache(cacheName), regionName);
+ return new InfinispanTimestampsRegion(manager.getCache(cacheName), regionName, transactionManager);
}
/**
@@ -233,6 +213,9 @@
public void start(Settings settings, Properties properties) throws CacheException {
log.debug("Starting Infinispan CacheManager");
try {
+ transactionManagerlookup = new HibernateTransactionManagerLookup(settings, properties);
+ transactionManager = transactionManagerlookup.getTransactionManager();
+
String configLoc = PropertiesHelper.getString(INFINISPAN_CONFIG_RESOURCE_PROP, properties, DEF_INFINISPAN_CONFIG_RESOURCE);
manager = createCacheManager(configLoc);
initGenericDataTypeOverrides();
@@ -244,51 +227,12 @@
dissectProperty(prefixLoc, key, properties);
}
}
- defineGenericDataTypeCacheConfigurations();
+ defineGenericDataTypeCacheConfigurations(settings, properties);
} catch (CacheException ce) {
throw ce;
} catch (Throwable t) {
throw new CacheException("Unable to start region factory", t);
}
-
-// if ((suffixLoc = key.indexOf(CONFIG_SUFFIX)) != -1) {
-// cfgOverride = getOrCreateConfig(key, prefixLoc, suffixLoc);
-// cfgOverride.setCache(PropertiesHelper.extractPropertyValue(key, properties));
-//// String name = key.substring(prefixLoc + PREFIX.length(), suffixLoc);
-//// cfgOverride = configs.get(name);
-//// if (cfgOverride == null) {
-//// cfgOverride = new DataTypeConfig();
-//// configs.put(name, cfgOverride);
-//// }
-//// String cache = null;
-//// if (name.equals(ENTITY_CACHE_RESOURCE_PROP)) {
-//// cache = PropertiesHelper.getString(ENTITY_CACHE_RESOURCE_PROP, properties, DEF_ENTITY_RESOURCE);
-//// } else if (name.equals(COLLECTION_CACHE_RESOURCE_PROP)) {
-//// cache = PropertiesHelper.getString(COLLECTION_CACHE_RESOURCE_PROP, properties, DEF_ENTITY_RESOURCE);
-//// } else if (name.equals(TIMESTAMP_CACHE_RESOURCE_PROP)) {
-//// cache = PropertiesHelper.getString(TIMESTAMP_CACHE_RESOURCE_PROP, properties, DEF_TIMESTAMP_RESOURCE);
-//// } else if (name.equals(QUERY_CACHE_RESOURCE_PROP)) {
-//// cache = PropertiesHelper.getString(QUERY_CACHE_RESOURCE_PROP, properties, DEF_QUERY_RESOURCE);
-//// } else {
-//// cache = PropertiesHelper.extractPropertyValue(key, properties);
-//// }
-//// cfgOverride.setCache(cache);
-// } else if ((suffixLoc = key.indexOf(STRATEGY_SUFFIX)) != -1) {
-// cfgOverride = getOrCreateConfig(key, prefixLoc, suffixLoc);
-// cfgOverride.setStrategy(PropertiesHelper.extractPropertyValue(key, properties));
-// } else if ((suffixLoc = key.indexOf(WAKE_UP_INTERVAL_SUFFIX)) != -1) {
-// cfgOverride = getOrCreateConfig(key, prefixLoc, suffixLoc);
-// cfgOverride.setWakeUpInterval(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
-// } else if ((suffixLoc = key.indexOf(MAX_ENTRIES_SUFFIX)) != -1) {
-// cfgOverride = getOrCreateConfig(key, prefixLoc, suffixLoc);
-// cfgOverride.setMaxEntries(PropertiesHelper.getInt(key, properties, -1));
-// } else if ((suffixLoc = key.indexOf(LIFESPAN_SUFFIX)) != -1) {
-// cfgOverride = getOrCreateConfig(key, prefixLoc, suffixLoc);
-// cfgOverride.setLifespan(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
-// } else if ((suffixLoc = key.indexOf(MAX_IDLE_SUFFIX)) != -1) {
-// cfgOverride = getOrCreateConfig(key, prefixLoc, suffixLoc);
-// cfgOverride.setMaxIdle(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
-// }
}
/**
@@ -341,7 +285,7 @@
typeOverrides.put(QUERY_KEY, queryOverrides);
return typeOverrides;
}
-
+
// private boolean isGenericDataTypeProperty(String property) {
// return property.startsWith(PREFIX + ENTITY_KEY) || property.startsWith(PREFIX + COLLECTION_KEY)
// || property.startsWith(PREFIX + QUERY_KEY) || property.startsWith(PREFIX + TIMESTAMP_KEY);
@@ -358,7 +302,7 @@
cfgOverride.setEvictionStrategy(PropertiesHelper.extractPropertyValue(key, properties));
} else if ((suffixLoc = key.indexOf(WAKE_UP_INTERVAL_SUFFIX)) != -1) {
cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
- cfgOverride.setEvictionWakeUpInterval(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
+ cfgOverride.setEvictionWakeUpInterval(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
} else if ((suffixLoc = key.indexOf(MAX_ENTRIES_SUFFIX)) != -1) {
cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
cfgOverride.setEvictionMaxEntries(PropertiesHelper.getInt(key, properties, -1));
@@ -399,19 +343,23 @@
return cfgOverride;
}
- private void defineGenericDataTypeCacheConfigurations() throws CacheException {
+ private void defineGenericDataTypeCacheConfigurations(Settings settings, Properties properties) throws CacheException {
String[] defaultGenericDataTypes = new String[]{ENTITY_KEY, COLLECTION_KEY, TIMESTAMPS_KEY, QUERY_KEY};
for (String type : defaultGenericDataTypes) {
TypeOverrides override = typeOverrides.get(type);
String cacheName = override.getCacheName();
Configuration newCacheCfg = override.createInfinispanConfiguration();
+ // Apply overrides
Configuration cacheConfig = manager.defineConfiguration(cacheName, cacheName, newCacheCfg);
+ // Configure transaction manager
+ cacheConfig = configureTransactionManager(cacheConfig, cacheName, properties);
+ manager.defineConfiguration(cacheName, cacheName, cacheConfig);
definedConfigurations.add(cacheName);
override.validateInfinispanConfiguration(cacheConfig);
}
}
- private Cache getCache(String regionName, String typeKey) {
+ private Cache getCache(String regionName, String typeKey, Properties properties) {
TypeOverrides regionOverride = typeOverrides.get(regionName);
if (!definedConfigurations.contains(regionName)) {
String templateCacheName = null;
@@ -429,6 +377,9 @@
templateCacheName = typeOverrides.get(typeKey).getCacheName();
regionCacheCfg = typeOverrides.get(typeKey).createInfinispanConfiguration();
}
+ // Configure transaction manager
+ regionCacheCfg = configureTransactionManager(regionCacheCfg, templateCacheName, properties);
+ // Apply overrides
manager.defineConfiguration(regionName, templateCacheName, regionCacheCfg);
definedConfigurations.add(regionName);
}
@@ -467,4 +418,18 @@
// // No region specific overrides, get a cache instance for the generic entity data type region
// return manager.getCache(regionName);
}
+
+ private Configuration configureTransactionManager(Configuration regionOverrides, String templateCacheName, Properties properties) {
+ // Get existing configuration to verify whether a tm was configured or not.
+ Configuration templateConfig = manager.defineConfiguration(templateCacheName, new Configuration());
+ String ispnTmLookupClassName = templateConfig.getTransactionManagerLookupClass();
+ String hbTmLookupClassName = org.hibernate.cache.infinispan.tm.HibernateTransactionManagerLookup.class.getName();
+ if (ispnTmLookupClassName != null && !ispnTmLookupClassName.equals(hbTmLookupClassName)) {
+ log.debug("Infinispan is configured [" + ispnTmLookupClassName + "] with a different transaction manager lookup " +
+ "class than Hibernate [" + hbTmLookupClassName + "]");
+ } else {
+ regionOverrides.setTransactionManagerLookup(transactionManagerlookup);
+ }
+ return regionOverrides;
+ }
}
\ No newline at end of file
Deleted: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TimestampTypeOverrides.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TimestampTypeOverrides.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TimestampTypeOverrides.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,42 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.hibernate.cache.infinispan;
-
-import org.hibernate.cache.CacheException;
-import org.infinispan.config.Configuration;
-import org.infinispan.config.Configuration.CacheMode;
-
-/**
- * TimestampTypeOverrides.
- *
- * @author Galder Zamarreño
- * @since 4.0
- */
-public class TimestampTypeOverrides extends TypeOverrides {
- @Override
- public void validateInfinispanConfiguration(Configuration configuration) throws CacheException {
- CacheMode cacheMode = configuration.getCacheMode();
- if (cacheMode.equals(CacheMode.INVALIDATION_ASYNC) || cacheMode.equals(CacheMode.INVALIDATION_SYNC)) {
- throw new CacheException("Timestamp cache cannot be configured with invalidation");
- }
- }
-}
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/InfinispanCollectionRegion.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/InfinispanCollectionRegion.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/InfinispanCollectionRegion.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,5 +1,9 @@
package org.hibernate.cache.infinispan.collection;
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CollectionRegion;
@@ -14,8 +18,8 @@
*/
public class InfinispanCollectionRegion extends BaseTransactionalDataRegion implements CollectionRegion {
- public InfinispanCollectionRegion(Cache<Object, Object> cache, String name, CacheDataDescription metadata) {
- super(cache, name, metadata);
+ public InfinispanCollectionRegion(Cache<Object, Object> cache, String name, CacheDataDescription metadata, TransactionManager transactionManager) {
+ super(cache, name, metadata, transactionManager);
}
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/InfinispanEntityRegion.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/InfinispanEntityRegion.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/InfinispanEntityRegion.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,5 +1,9 @@
package org.hibernate.cache.infinispan.entity;
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.EntityRegion;
@@ -14,8 +18,8 @@
*/
public class InfinispanEntityRegion extends BaseTransactionalDataRegion implements EntityRegion {
- public InfinispanEntityRegion(Cache<Object, Object> cache, String name, CacheDataDescription metadata) {
- super(cache, name, metadata);
+ public InfinispanEntityRegion(Cache<Object, Object> cache, String name, CacheDataDescription metadata, TransactionManager transactionManager) {
+ super(cache, name, metadata, transactionManager);
}
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,5 +1,9 @@
package org.hibernate.cache.infinispan.impl;
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
import org.hibernate.cache.CacheException;
import org.hibernate.cache.GeneralDataRegion;
import org.infinispan.Cache;
@@ -11,8 +15,8 @@
*/
public abstract class BaseGeneralDataRegion extends BaseRegion implements GeneralDataRegion {
- public BaseGeneralDataRegion(Cache<Object, Object> cache, String name) {
- super(cache, name);
+ public BaseGeneralDataRegion(Cache<Object, Object> cache, String name, TransactionManager transactionManager) {
+ super(cache, name, transactionManager);
}
public void evict(Object key) throws CacheException {
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,10 +1,20 @@
package org.hibernate.cache.infinispan.impl;
+import java.lang.reflect.Field;
import java.util.Map;
+import java.util.Properties;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
import org.hibernate.cache.CacheException;
import org.hibernate.cache.Region;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.hibernate.transaction.TransactionManagerLookupFactory;
import org.infinispan.Cache;
+import org.infinispan.context.Flag;
+import org.infinispan.factories.ComponentRegistry;
/**
* Support for Infinispan {@link Region}s. Handles common "utility" methods for an underlying named
@@ -17,10 +27,12 @@
abstract class BaseRegion implements Region {
private final Cache cache;
private final String name;
+ protected final TransactionManager transactionManager;
- public BaseRegion(Cache cache, String name) {
+ public BaseRegion(Cache cache, String name, TransactionManager transactionManager) {
this.cache = cache;
this.name = name;
+ this.transactionManager = transactionManager;
}
public Cache getCache() {
@@ -71,5 +83,100 @@
public void destroy() throws CacheException {
// TODO see if we need to do this even in spite of RF.shutdown()
}
+
+ /**
+ * Performs a JBoss Cache <code>get(Fqn, Object)</code> after first
+ * {@link #suspend suspending any ongoing transaction}. Wraps any exception
+ * in a {@link CacheException}. Ensures any ongoing transaction is resumed.
+ *
+ * @param key The key of the item to get
+ * @param opt any option to add to the get invocation. May be <code>null</code>
+ * @param suppressTimeout should any TimeoutException be suppressed?
+ * @return The retrieved object
+ * @throws CacheException issue managing transaction or talking to cache
+ */
+ protected Object suspendAndGet(Object key, Flag opt, boolean suppressTimeout) throws CacheException {
+ Transaction tx = suspend();
+ try {
+ if (suppressTimeout)
+ return CacheHelper.getAllowingTimeout(cache, key);
+ else
+ return CacheHelper.get(cache, key);
+ } finally {
+ resume(tx);
+ }
+ }
+
+ /**
+ * Tell the TransactionManager to suspend any ongoing transaction.
+ *
+ * @return the transaction that was suspended, or <code>null</code> if
+ * there wasn't one
+ */
+ protected Transaction suspend() {
+ Transaction tx = null;
+ try {
+ if (transactionManager != null) {
+ tx = transactionManager.suspend();
+ }
+ } catch (SystemException se) {
+ throw new CacheException("Could not suspend transaction", se);
+ }
+ return tx;
+ }
+
+ /**
+ * Tell the TransactionManager to resume the given transaction
+ *
+ * @param tx
+ * the transaction to suspend. May be <code>null</code>.
+ */
+ protected void resume(Transaction tx) {
+ try {
+ if (tx != null)
+ transactionManager.resume(tx);
+ } catch (Exception e) {
+ throw new CacheException("Could not resume transaction", e);
+ }
+ }
+
+// /**
+// * HACKY WAY TO GET THE TRANSACTION MANAGER, TODO: resolve it!
+// */
+// private static TransactionManager getTransactionManager(Properties properties) {
+//// return cache == null ? null : extractComponent(cache, TransactionManager.class);
+// return TransactionManagerLookupFactory.getTransactionManager(properties);
+// }
+//
+// public static <T> T extractComponent(Cache cache, Class<T> componentType) {
+// ComponentRegistry cr = extractComponentRegistry(cache);
+// return cr.getComponent(componentType);
+// }
+//
+// public static ComponentRegistry extractComponentRegistry(Cache cache) {
+// return (ComponentRegistry) extractField(cache, "componentRegistry");
+// }
+//
+// public static Object extractField(Object target, String fieldName) {
+// return extractField(target.getClass(), target, fieldName);
+// }
+//
+// public static Object extractField(Class type, Object target, String fieldName) {
+// Field field;
+// try {
+// field = type.getDeclaredField(fieldName);
+// field.setAccessible(true);
+// return field.get(target);
+// }
+// catch (Exception e) {
+// if (type.equals(Object.class)) {
+// e.printStackTrace();
+// return null;
+// } else {
+// // try with superclass!!
+// return extractField(type.getSuperclass(), target, fieldName);
+// }
+// }
+// }
}
\ No newline at end of file
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,5 +1,9 @@
package org.hibernate.cache.infinispan.impl;
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.TransactionalDataRegion;
import org.infinispan.Cache;
@@ -13,8 +17,8 @@
private final CacheDataDescription metadata;
- public BaseTransactionalDataRegion(Cache<Object, Object> cache, String name, CacheDataDescription metadata) {
- super(cache, name);
+ public BaseTransactionalDataRegion(Cache<Object, Object> cache, String name, CacheDataDescription metadata, TransactionManager transactionManager) {
+ super(cache, name, transactionManager);
this.metadata = metadata;
}
@@ -23,7 +27,7 @@
}
public boolean isTransactionAware() {
- return true;
+ return transactionManager != null;
}
}
\ No newline at end of file
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/InfinispanQueryResultsRegion.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/InfinispanQueryResultsRegion.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/InfinispanQueryResultsRegion.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,16 +1,85 @@
package org.hibernate.cache.infinispan.query;
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.infinispan.impl.BaseGeneralDataRegion;
+import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.hibernate.util.PropertiesHelper;
import org.infinispan.Cache;
+import org.infinispan.context.Flag;
/**
* @author Chris Bredesen
*/
-public class InfinispanQueryResultsRegion extends BaseGeneralDataRegion implements QueryResultsRegion {
+public class InfinispanQueryResultsRegion extends BaseTransactionalDataRegion implements QueryResultsRegion {
+ public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.infinispan.query.localonly";
- public InfinispanQueryResultsRegion(Cache<Object, Object> cache, String name) {
- super(cache, name);
+ private boolean localOnly;
+
+ public InfinispanQueryResultsRegion(Cache<Object, Object> cache, String name, Properties properties, TransactionManager transactionManager) {
+ super(cache, name, null, transactionManager);
+
+ // If JBC is using INVALIDATION, we don't want to propagate changes.
+ // We use the Timestamps cache to manage invalidation
+ localOnly = CacheHelper.isClusteredInvalidation(cache);
+ if (!localOnly) {
+ // We don't want to waste effort setting an option if JBC is
+ // already in LOCAL mode. If JBC is REPL_(A)SYNC then check
+ // if they passed an config option to disable query replication
+ localOnly = CacheHelper.isClusteredReplication(cache)
+ && PropertiesHelper.getBoolean(QUERY_CACHE_LOCAL_ONLY_PROP, properties, false);
+ }
}
+ public void evict(Object key) throws CacheException {
+ if (localOnly)
+ CacheHelper.removeKey(getCache(), key, Flag.CACHE_MODE_LOCAL);
+ else
+ CacheHelper.removeKey(getCache(), key);
+ }
+
+ public void evictAll() throws CacheException {
+ if (localOnly)
+ CacheHelper.removeAll(getCache(), Flag.CACHE_MODE_LOCAL);
+ else
+ CacheHelper.removeAll(getCache());
+ }
+
+ public Object get(Object key) throws CacheException {
+ // Don't hold the JBC node lock throughout the tx, as that
+ // prevents updates
+ // Add a zero (or low) timeout option so we don't block
+ // waiting for tx's that did a put to commit
+ return suspendAndGet(key, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT, true);
+ }
+
+ public void put(Object key, Object value) throws CacheException {
+ // Here we don't want to suspend the tx. If we do:
+ // 1) We might be caching query results that reflect uncommitted
+ // changes. No tx == no WL on cache node, so other threads
+ // can prematurely see those query results
+ // 2) No tx == immediate replication. More overhead, plus we
+ // spread issue #1 above around the cluster
+
+ // Add a zero (or quite low) timeout option so we don't block.
+ // Ignore any TimeoutException. Basically we forego caching the
+ // query result in order to avoid blocking.
+ // Reads are done with suspended tx, so they should not hold the
+ // lock for long. Not caching the query result is OK, since
+ // any subsequent read will just see the old result with its
+ // out-of-date timestamp; that result will be discarded and the
+ // db query performed again.
+ if (localOnly)
+ CacheHelper.putAllowingTimeout(getCache(), key, value, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT, Flag.CACHE_MODE_LOCAL);
+ else
+ CacheHelper.putAllowingTimeout(getCache(), key, value, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT);
+
+ }
+
}
\ No newline at end of file
Modified: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/InfinispanTimestampsRegion.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/InfinispanTimestampsRegion.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/InfinispanTimestampsRegion.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,16 +1,120 @@
package org.hibernate.cache.infinispan.timestamp;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheException;
import org.hibernate.cache.TimestampsRegion;
import org.hibernate.cache.infinispan.impl.BaseGeneralDataRegion;
+import org.hibernate.cache.infinispan.util.CacheHelper;
import org.infinispan.Cache;
+import org.infinispan.context.Flag;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
/**
+ * Defines the behavior of the timestamps cache region for Infinispan.
+ *
* @author Chris Bredesen
+ * @author Galder Zamarreño
*/
+ at Listener
public class InfinispanTimestampsRegion extends BaseGeneralDataRegion implements TimestampsRegion {
- public InfinispanTimestampsRegion(Cache<Object, Object> cache, String name) {
- super(cache, name);
+ private Map localCache = new ConcurrentHashMap();
+
+ public InfinispanTimestampsRegion(Cache<Object, Object> cache, String name, TransactionManager transactionManager) {
+ super(cache, name, transactionManager);
+ cache.addListener(this);
+ populateLocalCache();
}
+ @Override
+ public void evict(Object key) throws CacheException {
+ // TODO Is this a valid operation on a timestamps cache?
+ CacheHelper.evict(getCache(), key);
+ }
+
+ public void evictAll() throws CacheException {
+ // TODO Is this a valid operation on a timestamps cache?
+ CacheHelper.removeAll(getCache());
+ }
+
+ public Object get(Object key) throws CacheException {
+ Object value = localCache.get(key);
+ if (value == null) {
+ value = suspendAndGet(key, null, false);
+ if (value != null)
+ localCache.put(key, value);
+ }
+ return value;
+ }
+
+ public void put(Object key, Object value) throws CacheException {
+ // Don't hold the JBC node lock throughout the tx, as that
+ // prevents reads and other updates
+ Transaction tx = suspend();
+ try {
+ // We ensure ASYNC semantics (JBCACHE-1175)
+ CacheHelper.put(getCache(), key, value, Flag.FORCE_ASYNCHRONOUS);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ } finally {
+ resume(tx);
+ }
+ }
+
+ @Override
+ public void destroy() throws CacheException {
+ localCache.clear();
+ getCache().removeListener(this);
+ super.destroy();
+ }
+
+ /**
+ * Monitors cache events and updates the local cache
+ *
+ * @param event
+ */
+ @CacheEntryModified
+ public void nodeModified(CacheEntryModifiedEvent event) {
+ if (event.isPre()) return;
+ localCache.put(event.getKey(), event.getValue());
+ }
+
+ /**
+ * Monitors cache events and updates the local cache
+ *
+ * @param event
+ */
+ @CacheEntryRemoved
+ public void nodeRemoved(CacheEntryRemovedEvent event) {
+ if (event.isPre()) return;
+ localCache.remove(event.getKey());
+// Fqn fqn = event.getFqn();
+// Fqn regFqn = getRegionFqn();
+// if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
+// Object key = fqn.get(regFqn.size());
+// localCache.remove(key);
+// } else if (fqn.equals(regFqn)) {
+// localCache.clear();
+// }
+ }
+
+ /**
+ * Brings all data from the distributed cache into our local cache.
+ */
+ private void populateLocalCache() {
+ Set children = CacheHelper.getKeySet(getCache());
+ for (Object key : children)
+ get(key);
+ }
+
}
\ No newline at end of file
Copied: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java (from rev 17297, core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TimestampTypeOverrides.java)
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.hibernate.cache.infinispan.timestamp;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.infinispan.TypeOverrides;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.Configuration.CacheMode;
+import org.infinispan.eviction.EvictionStrategy;
+
+/**
+ * TimestampTypeOverrides.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+public class TimestampTypeOverrides extends TypeOverrides {
+ @Override
+ public void validateInfinispanConfiguration(Configuration configuration) throws CacheException {
+ CacheMode cacheMode = configuration.getCacheMode();
+ if (cacheMode.equals(CacheMode.INVALIDATION_ASYNC) || cacheMode.equals(CacheMode.INVALIDATION_SYNC)) {
+ throw new CacheException("Timestamp cache cannot be configured with invalidation");
+ }
+ EvictionStrategy strategy = configuration.getEvictionStrategy();
+ if (!strategy.equals(EvictionStrategy.NONE)) {
+ throw new CacheException("Timestamp cache cannot be configured with eviction");
+ }
+ }
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.hibernate.cache.infinispan.tm;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cfg.Settings;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+/**
+ * HibernateTransactionManagerLookup.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+public class HibernateTransactionManagerLookup implements org.infinispan.transaction.lookup.TransactionManagerLookup {
+ private final TransactionManagerLookup hibernateLookup;
+
+ private final Properties properties;
+
+ public HibernateTransactionManagerLookup(Settings settings, Properties properties) {
+ if (settings != null)
+ this.hibernateLookup = settings.getTransactionManagerLookup();
+ else
+ this.hibernateLookup = null;
+ this.properties = properties;
+ }
+
+ public TransactionManager getTransactionManager() throws Exception {
+ return hibernateLookup == null ? null : hibernateLookup.getTransactionManager(properties);
+ }
+
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,439 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.infinispan.util;
+
+import java.util.Set;
+
+import org.hibernate.cache.CacheException;
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.Flag;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper for dealing with Infinisan cache instances.
+ *
+ * @author Steve Ebersole
+ * @author Brian Stansberry
+ * @author Galder Zamarreño
+ */
+public class CacheHelper {
+
+ /** Key under which items are cached */
+ public static final String ITEM = "item";
+ /** Key and value used in a hack to create region root nodes */
+ public static final String DUMMY = "dummy";
+
+ private static final Logger log = LoggerFactory.getLogger(CacheHelper.class);
+
+ /**
+ * Disallow external instantiation of CacheHelper.
+ */
+ private CacheHelper() {
+ }
+
+ /**
+ * Is this cache participating in a cluster with invalidation?
+ *
+ * @param cache
+ * The cache to check.
+ * @return True if the cache is configured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredInvalidation(Cache cache) {
+ return isClusteredInvalidation(cache.getConfiguration().getCacheMode());
+ }
+
+ /**
+ * Does this cache mode indicate clustered invalidation?
+ *
+ * @param cacheMode
+ * The cache to check
+ * @return True if the cache mode is confiogured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredInvalidation(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.INVALIDATION_ASYNC
+ || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+ }
+
+ /**
+ * Is this cache participating in a cluster with replication?
+ *
+ * @param cache
+ * The cache to check.
+ * @return True if the cache is configured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredReplication(Cache cache) {
+ return isClusteredReplication(cache.getConfiguration().getCacheMode());
+ }
+
+ /**
+ * Does this cache mode indicate clustered replication?
+ *
+ * @param cacheMode
+ * The cache to check
+ * @return True if the cache mode is confiogured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredReplication(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.REPL_ASYNC || cacheMode == Configuration.CacheMode.REPL_SYNC;
+ }
+
+ public static boolean isSynchronous(Cache cache) {
+ return isSynchronous(cache.getConfiguration().getCacheMode());
+ }
+
+ public static boolean isSynchronous(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.REPL_SYNC || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+ }
+
+ public static Set getKeySet(Cache cache) {
+ return cache.keySet();
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>get(Fqn, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ */
+ public static Object get(Cache cache, Object key) throws CacheException {
+ try {
+ return cache.get(key);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>get(Fqn, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ */
+ public static Object getAllowingTimeout(Cache cache, Object key) throws CacheException {
+ try {
+ return cache.get(key);
+ } catch (TimeoutException ignored) {
+ // ignore it
+ return null;
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>put(Object, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ */
+ public static void put(Cache cache, Object key, Object value) throws CacheException {
+ put(cache, key, value, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>put(Object, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void put(Cache cache, Object key, Object value, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().put(key, value, option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>put(Object, Object)</code>, ignoring any {@link TimeoutException} and wrapping any other
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void putAllowingTimeout(Cache cache, Object key, Object value, Flag... option) throws CacheException {
+ try {
+ cache.getAdvancedCache().put(key, value, option);
+ } catch (TimeoutException allowed) {
+ // ignore it
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>putForExternalRead(Object, Object)</code>, wrapping any exception in a
+ * {@link CacheException}. Ignores any JBoss Cache {@link TimeoutException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ */
+ public static boolean putForExternalRead(Cache cache, Object key, Object value) throws CacheException {
+ return putForExternalRead(cache, key, value, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>putForExternalRead(Object, Object)</code>, wrapping any exception in a
+ * {@link CacheException}. Ignores any JBoss Cache {@link TimeoutException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static boolean putForExternalRead(Cache cache, Object key, Object value, Flag... option) throws CacheException {
+ try {
+ cache.getAdvancedCache().putForExternalRead(key, value, option);
+ return true;
+ } catch (TimeoutException te) {
+ // ignore!
+ log.debug("ignoring write lock acquisition failure");
+ return false;
+ } catch (Throwable t) {
+ throw new CacheException(t);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>removeNode(Fqn)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ */
+ public static void remove(Cache cache, Object key) throws CacheException {
+ remove(cache, key, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>removeNode(Fqn)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void remove(Cache cache, Object key, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().remove(key, option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any exception in a
+ * {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ */
+ public static void removeAll(Cache cache) throws CacheException {
+ try {
+ cache.clear();
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any exception in a
+ * {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void removeAll(Cache cache, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().clear(option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any exception in a
+ * {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void removeKey(Cache cache, Object key, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().remove(key, option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ public static void removeKey(Cache cache, Object key) throws CacheException {
+ try {
+ cache.remove(key);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ public static void evict(Cache cache, Object key) throws CacheException {
+ try {
+ cache.evict(key);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+
+// public static Node addNode(Cache cache, Fqn fqn, boolean localOnly, boolean resident) throws CacheException {
+// try {
+// Option option = null;
+// if (localOnly) {
+// option = new Option();
+// option.setCacheModeLocal(localOnly);
+// }
+//
+// Node root = cache.getRoot();
+// setInvocationOption(cache, option);
+// // FIXME hack to work around fact that calling
+// // Node added = root.addChild( fqn ); doesn't
+// // properly set the version on the node
+// Node added = null;
+// if (version == null) {
+// added = root.addChild(fqn);
+// } else {
+// cache.put(fqn, DUMMY, DUMMY);
+// added = root.getChild(fqn);
+// }
+// if (resident)
+// added.setResident(true);
+// return added;
+// } catch (Exception e) {
+// throw new CacheException(e);
+// }
+// }
+
+ /**
+// * Assigns the given Option to the cache's {@link InvocationContext}. Does nothing if
+// * <code>option</code> is <code>null</code>.
+// *
+// * @param cache
+// * the cache. Cannot be <code>null</code>.
+// * @param option
+// * the option. May be <code>null</code>.
+// *
+// * @see {@link Cache#getInvocationContext()}
+// * @see {@link InvocationContext#setOptionOverrides(Option)}
+// */
+// public static void setInvocationOption(Cache cache, Option option) {
+// if (option != null) {
+// cache.getInvocationContext().setOptionOverrides(option);
+// }
+// }
+
+// /**
+// * Creates an {@link Option} using the given {@link DataVersion} and passes it to
+// * {@link #setInvocationOption(Cache, Option)}.
+// *
+// * @param cache
+// * the cache to set the Option on. Cannot be <code>null</code>.
+// * @param version
+// * the DataVersion to set. Cannot be <code>null</code>.
+// */
+// public static void setDataVersionOption(Cache cache, DataVersion version) {
+// Option option = new Option();
+// option.setDataVersion(version);
+// setInvocationOption(cache, option);
+// }
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,194 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.GeneralDataRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.infinispan.Cache;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of QueryResultsRegion and TimestampsRegion.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionImplTestCase {
+ protected static final String KEY = "Key";
+
+ protected static final String VALUE1 = "value1";
+ protected static final String VALUE2 = "value2";
+
+ public AbstractGeneralDataRegionTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void putInRegion(Region region, Object key, Object value) {
+ ((GeneralDataRegion) region).put(key, value);
+ }
+
+ @Override
+ protected void removeFromRegion(Region region, Object key) {
+ ((GeneralDataRegion) region).evict(key);
+ }
+
+ /**
+ * Test method for {@link QueryResultsRegion#evict(java.lang.Object)}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * CollectionRegionAccessStrategy API.
+ */
+ public void testEvict() throws Exception {
+ evictOrRemoveTest();
+ }
+
+ private void evictOrRemoveTest() throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache localCache = getInfinispanCache(regionFactory);
+ boolean invalidation = CacheHelper.isClusteredInvalidation(localCache);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+
+ cfg = createConfiguration();
+ regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+
+ assertNull("local is clean", localRegion.get(KEY));
+ assertNull("remote is clean", remoteRegion.get(KEY));
+
+ localRegion.put(KEY, VALUE1);
+ assertEquals(VALUE1, localRegion.get(KEY));
+
+ // allow async propagation
+ sleep(250);
+ Object expected = invalidation ? null : VALUE1;
+ assertEquals(expected, remoteRegion.get(KEY));
+
+ localRegion.evict(KEY);
+
+ assertEquals(null, localRegion.get(KEY));
+
+ assertEquals(null, remoteRegion.get(KEY));
+ }
+
+ protected abstract String getStandardRegionName(String regionPrefix);
+
+ /**
+ * Test method for {@link QueryResultsRegion#evictAll()}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * CollectionRegionAccessStrategy API.
+ */
+ public void testEvictAll() throws Exception {
+ evictOrRemoveAllTest("entity");
+ }
+
+ private void evictOrRemoveAllTest(String configName) throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache localCache = getInfinispanCache(regionFactory);
+ boolean invalidation = CacheHelper.isClusteredInvalidation(localCache);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+
+ cfg = createConfiguration();
+ regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache remoteCache = getInfinispanCache(regionFactory);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+ String regionName = REGION_PREFIX;
+
+ Set children = CacheHelper.getKeySet(localCache);
+ assertEquals("No children in " + children, 0, children.size());
+
+ children = CacheHelper.getKeySet(remoteCache);
+ assertEquals("No children in " + children, 0, children.size());
+
+ assertNull("local is clean", localRegion.get(KEY));
+ assertNull("remote is clean", remoteRegion.get(KEY));
+
+ localRegion.put(KEY, VALUE1);
+ assertEquals(VALUE1, localRegion.get(KEY));
+
+ // Allow async propagation
+ sleep(250);
+
+ remoteRegion.put(KEY, VALUE1);
+ assertEquals(VALUE1, remoteRegion.get(KEY));
+
+ // Allow async propagation
+ sleep(250);
+
+ localRegion.evictAll();
+
+ // This should re-establish the region root node in the optimistic case
+ assertNull(localRegion.get(KEY));
+
+ // Re-establishing the region root on the local node doesn't
+ // propagate it to other nodes. Do a get on the remote node to re-establish
+ // This only adds a node in the case of optimistic locking
+ assertEquals(null, remoteRegion.get(KEY));
+
+ assertEquals("local is clean", null, localRegion.get(KEY));
+ assertEquals("remote is clean", null, remoteRegion.get(KEY));
+ }
+
+ protected Configuration createConfiguration() {
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, false, true);
+ return cfg;
+ }
+
+ protected void rollback() {
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+}
\ No newline at end of file
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,97 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.junit.UnitTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestSupport;
+import org.infinispan.Cache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for all non-functional tests of Infinispan integration.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractNonFunctionalTestCase extends UnitTestCase {
+
+ public static final String REGION_PREFIX = "test";
+
+ private CacheTestSupport testSupport;
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ public AbstractNonFunctionalTestCase(String name) {
+ super(name);
+ testSupport = new CacheTestSupport(log);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ testSupport.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ testSupport.tearDown();
+ }
+
+ protected void registerCache(Cache cache) {
+ testSupport.registerCache(cache);
+ }
+
+ protected void unregisterCache(Cache cache) {
+ testSupport.unregisterCache(cache);
+ }
+
+ protected void registerFactory(RegionFactory factory) {
+ testSupport.registerFactory(factory);
+ }
+
+ protected void unregisterFactory(RegionFactory factory) {
+ testSupport.unregisterFactory(factory);
+ }
+
+ protected CacheTestSupport getCacheTestSupport() {
+ return testSupport;
+ }
+
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ }
+ catch (InterruptedException e) {
+ log.warn("Interrupted during sleep", e);
+ }
+ }
+
+ protected void avoidConcurrentFlush() {
+ testSupport.avoidConcurrentFlush();
+ }
+}
\ No newline at end of file
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,64 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.infinispan.Cache;
+import org.infinispan.manager.DefaultCacheManager;
+import org.jgroups.JChannelFactory;
+
+/**
+ * Base class for tests of Region implementations.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractRegionImplTestCase extends AbstractNonFunctionalTestCase {
+
+ public AbstractRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ protected abstract Cache getInfinispanCache(InfinispanRegionFactory regionFactory);
+
+ protected abstract Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd);
+
+ protected abstract void putInRegion(Region region, Object key, Object value);
+
+ protected abstract void removeFromRegion(Region region, Object key);
+
+ protected CacheDataDescription getCacheDataDescription() {
+ return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+ }
+
+}
Modified: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -287,8 +287,6 @@
fail("Should have failed saying that invalidation is not allowed for timestamp caches.");
} catch(CacheException ce) {
}
-
- fail("Add more validations!");
}
public void testBuildDefaultTimestampsRegion() {
@@ -342,26 +340,62 @@
}
}
- public void testBuildTimestamRegionWithOverrides() {
+ public void testBuildTimestamRegionWithCacheNameOverride() {
final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
Properties p = new Properties();
InfinispanRegionFactory factory = new InfinispanRegionFactory();
p.setProperty("hibernate.cache.infinispan.timestamps.cfg", "mytimestamps-cache");
- p.setProperty("hibernate.cache.infinispan.entity.eviction.strategy", "FIFO");
- p.setProperty("hibernate.cache.infinispan.entity.eviction.wake_up_interval", "3000");
- p.setProperty("hibernate.cache.infinispan.entity.eviction.max_entries", "10000");
factory.start(null, p);
CacheManager manager = factory.getCacheManager();
manager.getGlobalConfiguration().setTransportClass(null);
try {
InfinispanTimestampsRegion region = (InfinispanTimestampsRegion) factory.buildTimestampsRegion(timestamps, p);
- assertTrue(factory.getDefinedConfigurations().contains(timestamps));
+ assertTrue(factory.getDefinedConfigurations().contains("mytimestamps-cache"));
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildTimestamRegionWithFifoEvictionOverride() {
+ final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
+ Properties p = new Properties();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ p.setProperty("hibernate.cache.infinispan.timestamps.cfg", "mytimestamps-cache");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.strategy", "FIFO");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.max_entries", "10000");
+ try {
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ InfinispanTimestampsRegion region = (InfinispanTimestampsRegion) factory.buildTimestampsRegion(timestamps, p);
+ assertTrue(factory.getDefinedConfigurations().contains("mytimestamps-cache"));
fail("Should fail cos no eviction configurations are allowed for timestamp caches");
+ } catch(CacheException ce) {
} finally {
factory.stop();
}
}
+ public void testBuildTimestamRegionWithNoneEvictionOverride() {
+ final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
+ Properties p = new Properties();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ p.setProperty("hibernate.cache.infinispan.timestamps.cfg", "timestamps-none-eviction");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.strategy", "NONE");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.max_entries", "10000");
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ InfinispanTimestampsRegion region = (InfinispanTimestampsRegion) factory.buildTimestampsRegion(timestamps, p);
+ assertTrue(factory.getDefinedConfigurations().contains("timestamps-none-eviction"));
+ } finally {
+ factory.stop();
+ }
+ }
+
public void testBuildQueryRegion() {
final String query = "org.hibernate.cache.StandardQueryCache";
Properties p = new Properties();
Copied: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java (from rev 17244, core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractInfinispanTestCase.java)
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,104 @@
+package org.hibernate.test.cache.infinispan.functional;
+
+import java.util.Map;
+
+import org.hibernate.Session;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.stat.SecondLevelCacheStatistics;
+import org.hibernate.stat.Statistics;
+
+public abstract class AbstractFunctionalTestCase extends FunctionalTestCase {
+ private final String cacheConcurrencyStrategy;
+
+ public AbstractFunctionalTestCase(String string, String cacheConcurrencyStrategy) {
+ super(string);
+ this.cacheConcurrencyStrategy = cacheConcurrencyStrategy;
+ }
+
+ public String[] getMappings() {
+ return new String[] { "cache/infinispan/functional/Item.hbm.xml" };
+ }
+
+ @Override
+ public String getCacheConcurrencyStrategy() {
+ return cacheConcurrencyStrategy;
+ }
+
+ public void testEntityCache() {
+ Item item = new Item("chris", "Chris's Item");
+
+ Session s = openSession();
+ Statistics stats = s.getSessionFactory().getStatistics();
+ s.getTransaction().begin();
+ s.persist(item);
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ Item found = (Item) s.load(Item.class, item.getId());
+ System.out.println(stats);
+ assertEquals(item.getDescription(), found.getDescription());
+ assertEquals(0, stats.getSecondLevelCacheMissCount());
+ assertEquals(1, stats.getSecondLevelCacheHitCount());
+ s.delete(found);
+ s.close();
+ }
+
+ public void testQueryCache() {
+ Item item = new Item("chris", "Chris's Item");
+
+ Session s = openSession();
+ s.getTransaction().begin();
+ s.persist(item);
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.createQuery("from Item").setCacheable(true).list();
+ s.close();
+
+ s = openSession();
+ Statistics stats = s.getSessionFactory().getStatistics();
+ s.createQuery("from Item").setCacheable(true).list();
+ assertEquals(1, stats.getQueryCacheHitCount());
+ s.createQuery("delete from Item").executeUpdate();
+ s.close();
+ }
+
+ public void testCollectionCache() {
+ Item item = new Item("chris", "Chris's Item");
+ Item another = new Item("another", "Owned Item");
+ item.addItem(another);
+
+ Session s = openSession();
+ s.getTransaction().begin();
+ s.persist(item);
+ s.persist(another);
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ Statistics stats = s.getSessionFactory().getStatistics();
+ Item loaded = (Item) s.load(Item.class, item.getId());
+ assertEquals(1, loaded.getItems().size());
+ s.close();
+
+ s = openSession();
+ SecondLevelCacheStatistics cStats = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
+ Item loadedWithCachedCollection = (Item) s.load(Item.class, item.getId());
+ stats.logSummary();
+ assertEquals(item.getName(), loadedWithCachedCollection.getName());
+ assertEquals(item.getItems().size(), loadedWithCachedCollection.getItems().size());
+ assertEquals(1, cStats.getHitCount());
+ s.close();
+ }
+
+ public void testEmptySecondLevelCacheEntry() throws Exception {
+ getSessions().evictEntity(Item.class.getName());
+ Statistics stats = getSessions().getStatistics();
+ stats.clear();
+ SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
+ Map cacheEntries = statistics.getEntries();
+ assertEquals(0, cacheEntries.size());
+ }
+}
\ No newline at end of file
Deleted: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractInfinispanTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractInfinispanTestCase.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractInfinispanTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,104 +0,0 @@
-package org.hibernate.test.cache.infinispan.functional;
-
-import java.util.Map;
-
-import org.hibernate.Session;
-import org.hibernate.junit.functional.FunctionalTestCase;
-import org.hibernate.stat.SecondLevelCacheStatistics;
-import org.hibernate.stat.Statistics;
-
-public abstract class AbstractInfinispanTestCase extends FunctionalTestCase {
- private final String cacheConcurrencyStrategy;
-
- public AbstractInfinispanTestCase(String string, String cacheConcurrencyStrategy) {
- super(string);
- this.cacheConcurrencyStrategy = cacheConcurrencyStrategy;
- }
-
- public String[] getMappings() {
- return new String[] { "cache/infinispan/functional/Item.hbm.xml" };
- }
-
- @Override
- public String getCacheConcurrencyStrategy() {
- return cacheConcurrencyStrategy;
- }
-
- public void testEntityCache() {
- Item item = new Item("chris", "Chris's Item");
-
- Session s = openSession();
- Statistics stats = s.getSessionFactory().getStatistics();
- s.getTransaction().begin();
- s.persist(item);
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- Item found = (Item) s.load(Item.class, item.getId());
- System.out.println(stats);
- assertEquals(item.getDescription(), found.getDescription());
- assertEquals(0, stats.getSecondLevelCacheMissCount());
- assertEquals(1, stats.getSecondLevelCacheHitCount());
- s.delete(found);
- s.close();
- }
-
- public void testQueryCache() {
- Item item = new Item("chris", "Chris's Item");
-
- Session s = openSession();
- s.getTransaction().begin();
- s.persist(item);
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.createQuery("from Item").setCacheable(true).list();
- s.close();
-
- s = openSession();
- Statistics stats = s.getSessionFactory().getStatistics();
- s.createQuery("from Item").setCacheable(true).list();
- assertEquals(1, stats.getQueryCacheHitCount());
- s.createQuery("delete from Item").executeUpdate();
- s.close();
- }
-
- public void testCollectionCache() {
- Item item = new Item("chris", "Chris's Item");
- Item another = new Item("another", "Owned Item");
- item.addItem(another);
-
- Session s = openSession();
- s.getTransaction().begin();
- s.persist(item);
- s.persist(another);
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- Statistics stats = s.getSessionFactory().getStatistics();
- Item loaded = (Item) s.load(Item.class, item.getId());
- assertEquals(1, loaded.getItems().size());
- s.close();
-
- s = openSession();
- SecondLevelCacheStatistics cStats = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
- Item loadedWithCachedCollection = (Item) s.load(Item.class, item.getId());
- stats.logSummary();
- assertEquals(item.getName(), loadedWithCachedCollection.getName());
- assertEquals(item.getItems().size(), loadedWithCachedCollection.getItems().size());
- assertEquals(1, cStats.getHitCount());
- s.close();
- }
-
- public void testEmptySecondLevelCacheEntry() throws Exception {
- getSessions().evictEntity(Item.class.getName());
- Statistics stats = getSessions().getStatistics();
- stats.clear();
- SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
- Map cacheEntries = statistics.getEntries();
- assertEquals(0, cacheEntries.size());
- }
-}
\ No newline at end of file
Modified: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -1,6 +1,6 @@
package org.hibernate.test.cache.infinispan.functional;
-public class BasicReadOnlyTestCase extends AbstractInfinispanTestCase {
+public class BasicReadOnlyTestCase extends AbstractFunctionalTestCase {
public BasicReadOnlyTestCase(String string) {
super(string, "read-only");
Modified: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -7,7 +7,7 @@
import org.hibernate.cache.entry.CacheEntry;
import org.hibernate.stat.SecondLevelCacheStatistics;
-public class BasicTransactionalTestCase extends AbstractInfinispanTestCase {
+public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
public BasicTransactionalTestCase(String string) {
super(string, "transactional");
Modified: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -25,6 +25,8 @@
import java.util.List;
import java.util.Set;
+import javax.transaction.TransactionManager;
+
import org.hibernate.FlushMode;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
@@ -34,6 +36,8 @@
import org.hibernate.test.cache.infinispan.functional.Customer;
import org.hibernate.test.tm.SimpleJtaTransactionManagerImpl;
import org.hibernate.transaction.CMTTransactionFactory;
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.hibernate.util.ReflectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,6 +50,8 @@
public class BulkOperationsTestCase extends FunctionalTestCase {
private static final Logger log = LoggerFactory.getLogger(BulkOperationsTestCase.class);
+
+ private TransactionManager tm;
public BulkOperationsTestCase(String string) {
super(string);
@@ -65,11 +71,13 @@
}
protected Class getConnectionProviderClass() {
- return org.hibernate.test.tm.ConnectionProviderImpl.class;
+// return org.hibernate.test.tm.ConnectionProviderImpl.class;
+ return org.hibernate.test.cache.infinispan.tm.XaConnectionProvider.class;
}
- protected Class getTransactionManagerLookupClass() {
- return org.hibernate.test.tm.TransactionManagerLookupImpl.class;
+ protected Class<? extends TransactionManagerLookup> getTransactionManagerLookupClass() {
+ return org.hibernate.test.cache.infinispan.tm.XaTransactionManagerLookup.class;
+// return org.hibernate.test.tm.TransactionManagerLookupImpl.class;
}
public void configure(Configuration cfg) {
@@ -84,9 +92,12 @@
cfg.setProperty( Environment.TRANSACTION_STRATEGY, transactionFactory.getName());
}
- public void testBulkOperations() throws Exception {
+ public void testBulkOperations() throws Throwable {
System.out.println("*** testBulkOperations()");
+ boolean cleanedUp = false;
try {
+ tm = getTransactionManagerLookupClass().newInstance().getTransactionManager(null);
+
createContacts();
List<Integer> rhContacts = getContactsByCustomer("Red Hat");
@@ -118,21 +129,30 @@
List<Integer> updated = getContactsByTLF("Updated");
assertNotNull("Got updated contacts", updated);
assertEquals("Updated contacts", 5, updated.size());
+ } catch(Throwable t) {
+ cleanedUp = true;
+ log.debug("Exceptional cleanup");
+ cleanup(true);
+ throw t;
} finally {
// cleanup the db so we can run this test multiple times w/o restarting the cluster
- cleanup();
+ if (!cleanedUp) {
+ log.debug("Non exceptional cleanup");
+ cleanup(false);
+ }
}
}
public void createContacts() throws Exception {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ log.debug("Create 10 contacts");
+ tm.begin();
try {
for (int i = 0; i < 10; i++)
createCustomer(i);
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ tm.commit();
} catch (Exception e) {
log.error("Unable to create customer", e);
- SimpleJtaTransactionManagerImpl.getInstance().rollback();
+ tm.rollback();
throw e;
}
}
@@ -142,16 +162,20 @@
deleteHQL += " (select customer FROM Customer as customer ";
deleteHQL += " where customer.name = :cName)";
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ tm.begin();
try {
Session session = getSessions().getCurrentSession();
int rowsAffected = session.createQuery(deleteHQL).setFlushMode(FlushMode.AUTO)
.setParameter("cName", "Red Hat").executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ tm.commit();
return rowsAffected;
} catch (Exception e) {
- SimpleJtaTransactionManagerImpl.getInstance().rollback();
+ try {
+ tm.rollback();
+ } catch (Exception ee) {
+ // ignored
+ }
throw e;
}
}
@@ -160,16 +184,17 @@
String selectHQL = "select contact.id from Contact contact";
selectHQL += " where contact.customer.name = :cName";
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ log.debug("Get contacts for customer " + customerName);
+ tm.begin();
try {
Session session = getSessions().getCurrentSession();
List results = session.createQuery(selectHQL).setFlushMode(FlushMode.AUTO).setParameter("cName", customerName)
.list();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ tm.commit();
return results;
} catch (Exception e) {
- SimpleJtaTransactionManagerImpl.getInstance().rollback();
+ tm.rollback();
throw e;
}
}
@@ -178,15 +203,15 @@
String selectHQL = "select contact.id from Contact contact";
selectHQL += " where contact.tlf = :cTLF";
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ tm.begin();
try {
Session session = getSessions().getCurrentSession();
List results = session.createQuery(selectHQL).setFlushMode(FlushMode.AUTO).setParameter("cTLF", tlf).list();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ tm.commit();
return results;
} catch (Exception e) {
- SimpleJtaTransactionManagerImpl.getInstance().rollback();
+ tm.rollback();
throw e;
}
}
@@ -194,51 +219,72 @@
public int updateContacts(String name, String newTLF) throws Exception {
String updateHQL = "update Contact set tlf = :cNewTLF where name = :cName";
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ tm.begin();
try {
Session session = getSessions().getCurrentSession();
int rowsAffected = session.createQuery(updateHQL).setFlushMode(FlushMode.AUTO).setParameter("cNewTLF", newTLF)
.setParameter("cName", name).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ tm.commit();
return rowsAffected;
} catch (Exception e) {
- SimpleJtaTransactionManagerImpl.getInstance().rollback();
+ tm.rollback();
throw e;
}
}
public Contact getContact(Integer id) throws Exception {
-
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ tm.begin();
try {
Session session = getSessions().getCurrentSession();
Contact contact = (Contact) session.get(Contact.class, id);
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ tm.commit();
return contact;
} catch (Exception e) {
- SimpleJtaTransactionManagerImpl.getInstance().rollback();
+ tm.rollback();
throw e;
}
}
- public void cleanup() throws Exception {
+// public void cleanup() throws Exception {
+// String deleteContactHQL = "delete from Contact";
+// String deleteCustomerHQL = "delete from Customer";
+// tm.begin();
+// try {
+// Session session = getSessions().getCurrentSession();
+// session.createQuery(deleteContactHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
+// session.createQuery(deleteCustomerHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
+// tm.commit();
+// } catch (Exception e) {
+// try {
+// tm.rollback();
+// } catch (Exception ee) {
+// // ignored
+// }
+// throw e;
+// }
+// }
+
+ public void cleanup(boolean ignore) throws Exception {
String deleteContactHQL = "delete from Contact";
String deleteCustomerHQL = "delete from Customer";
-
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ tm.begin();
try {
-
Session session = getSessions().getCurrentSession();
session.createQuery(deleteContactHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
session.createQuery(deleteCustomerHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ tm.commit();
} catch (Exception e) {
- SimpleJtaTransactionManagerImpl.getInstance().rollback();
- throw e;
+ if (!ignore) {
+ try {
+ tm.rollback();
+ } catch (Exception ee) {
+ // ignored
+ }
+ throw e;
+ }
}
-
}
private Customer createCustomer(int id) throws Exception {
Modified: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -25,7 +25,11 @@
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
@@ -34,7 +38,9 @@
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
+import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,6 +57,8 @@
private LinkedList synchronizations;
private Connection connection; // the only resource we care about is jdbc connection
private final DualNodeJtaTransactionManagerImpl jtaTransactionManager;
+ private List<XAResource> enlistedResources = new ArrayList<XAResource>();
+ private Xid xid = new DualNodeJtaTransactionXid();
public DualNodeJtaTransactionImpl(DualNodeJtaTransactionManagerImpl jtaTransactionManager) {
this.jtaTransactionManager = jtaTransactionManager;
@@ -69,11 +77,17 @@
rollback();
} else {
status = Status.STATUS_PREPARING;
-
+
for (int i = 0; i < synchronizations.size(); i++) {
Synchronization s = (Synchronization) synchronizations.get(i);
s.beforeCompletion();
}
+
+ if (!runXaResourcePrepare()) {
+ status = Status.STATUS_ROLLING_BACK;
+ } else {
+ status = Status.STATUS_PREPARED;
+ }
status = Status.STATUS_COMMITTING;
@@ -86,7 +100,10 @@
throw new SystemException();
}
}
+
+ runXaResourceCommitTx();
+
status = Status.STATUS_COMMITTED;
for (int i = 0; i < synchronizations.size(); i++) {
@@ -100,6 +117,8 @@
}
public void rollback() throws IllegalStateException, SystemException {
+ status = Status.STATUS_ROLLING_BACK;
+ runXaResourceRollback();
status = Status.STATUS_ROLLEDBACK;
if (connection != null) {
@@ -149,11 +168,86 @@
public boolean enlistResource(XAResource xaResource) throws RollbackException,
IllegalStateException, SystemException {
- return false;
+ enlistedResources.add(xaResource);
+ try {
+ xaResource.start(xid, 0);
+ } catch (XAException e) {
+ log.error("Got an exception", e);
+ throw new SystemException(e.getMessage());
+ }
+ return true;
}
public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException,
SystemException {
- return false;
+ throw new SystemException("not supported");
}
+
+ public Collection<XAResource> getEnlistedResources() {
+ return enlistedResources;
+ }
+
+ private boolean runXaResourcePrepare() throws SystemException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.prepare(xid);
+ } catch (XAException e) {
+ log.trace("The resource wants to rollback!", e);
+ return false;
+ } catch (Throwable th) {
+ log.error("Unexpected error from resource manager!", th);
+ throw new SystemException(th.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private void runXaResourceRollback() {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.rollback(xid);
+ } catch (XAException e) {
+ log.warn("Error while rolling back",e);
+ }
+ }
+ }
+
+ private boolean runXaResourceCommitTx() throws HeuristicMixedException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.commit(xid, false);//todo we only support one phase commit for now, change this!!!
+ } catch (XAException e) {
+ log.warn("exception while committing",e);
+ throw new HeuristicMixedException(e.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private static class DualNodeJtaTransactionXid implements Xid {
+ private static AtomicInteger txIdCounter = new AtomicInteger(0);
+ private int id = txIdCounter.incrementAndGet();
+
+ public int getFormatId() {
+ return id;
+ }
+
+ public byte[] getGlobalTransactionId() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ public byte[] getBranchQualifier() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" +
+ "id=" + id +
+ '}';
+ }
+ }
}
Modified: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java 2009-08-18 17:23:57 UTC (rev 17354)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -36,7 +36,9 @@
import org.infinispan.manager.CacheManager;
import org.infinispan.marshall.MarshalledValue;
import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent;
import org.jboss.util.collection.ConcurrentSet;
import org.slf4j.Logger;
@@ -138,12 +140,12 @@
// Modify customer in remote
remoteListener.clear();
ids = modifyCustomer(ids.customerId, remoteFactory, remoteTM);
- assertLoadedFromCache(remoteListener, ids.customerId, ids.contactIds);
+ assertLoadedFromCache(remoteListener, ids.customerId, ids.contactIds);
// After modification, local cache should have been invalidated and hence should be empty
assertTrue(localCollectionCache.isEmpty());
assertTrue(localCustomerCache.isEmpty());
- assertTrue(localContactCache.isEmpty());
+ assertTrue(localContactCache.isEmpty());
} catch (Exception e) {
log.error("Error", e);
throw e;
@@ -328,7 +330,6 @@
@CacheEntryVisited
public void nodeVisited(CacheEntryVisitedEvent event) {
log.debug(event.toString());
-
if (!event.isPre()) {
MarshalledValue mv = (MarshalledValue) event.getKey();
CacheKey cacheKey = (CacheKey) mv.get();
@@ -336,7 +337,7 @@
String key = (String) cacheKey.getEntityOrRoleName() + '#' + primKey;
log.debug("MyListener[" + name +"] - Visiting key " + key);
// String name = fqn.toString();
- String token = ".functional.cluster.";
+ String token = ".functional.";
int index = key.indexOf(token);
if (index > -1) {
index += token.length();
@@ -346,6 +347,27 @@
}
}
}
+
+// @CacheEntryModified
+// public void nodeModified(CacheEntryModifiedEvent event) {
+// log.debug(event.toString());
+// if (!event.isPre()) {
+// MarshalledValue mv = (MarshalledValue) event.getKey();
+// CacheKey cacheKey = (CacheKey) mv.get();
+// Integer primKey = (Integer) cacheKey.getKey();
+// String key = (String) cacheKey.getEntityOrRoleName() + '#' + primKey;
+// log.debug("MyListener[" + name +"] - Modified key " + key);
+// // String name = fqn.toString();
+// String token = ".functional.";
+// int index = key.indexOf(token);
+// if (index > -1) {
+// index += token.length();
+// key = key.substring(index);
+// log.debug("MyListener[" + name +"] - recording modification of " + key);
+// visited.add(key);
+// }
+// }
+// }
}
private class IdContainer {
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,299 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.query;
+
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.StandardQueryCache;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.infinispan.Cache;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
+import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+import org.infinispan.util.concurrent.IsolationLevel;
+
+/**
+ * Tests of QueryResultRegionImpl.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
+
+ // protected static final String REGION_NAME = "test/" + StandardQueryCache.class.getName();
+
+ /**
+ * Create a new EntityRegionImplTestCase.
+ *
+ * @param name
+ */
+ public QueryRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties,
+ CacheDataDescription cdd) {
+ return regionFactory.buildQueryResultsRegion(regionName, properties);
+ }
+
+ @Override
+ protected String getStandardRegionName(String regionPrefix) {
+ return regionPrefix + "/" + StandardQueryCache.class.getName();
+ }
+
+ @Override
+ protected Cache getInfinispanCache(InfinispanRegionFactory regionFactory) {
+ return regionFactory.getCacheManager().getCache("local-query");
+ }
+
+ public void testPutDoesNotBlockGet() throws Exception {
+ putDoesNotBlockGetTest();
+ }
+
+ private void putDoesNotBlockGetTest() throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(getStandardRegionName(REGION_PREFIX), cfg
+ .getProperties());
+
+ region.put(KEY, VALUE1);
+ assertEquals(VALUE1, region.get(KEY));
+
+ final CountDownLatch readerLatch = new CountDownLatch(1);
+ final CountDownLatch writerLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ final ExceptionHolder holder = new ExceptionHolder();
+
+ Thread reader = new Thread() {
+ public void run() {
+ try {
+ BatchModeTransactionManager.getInstance().begin();
+ log.debug("Transaction began, get value for key");
+ assertTrue(VALUE2.equals(region.get(KEY)) == false);
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (AssertionFailedError e) {
+ holder.a1 = e;
+ rollback();
+ } catch (Exception e) {
+ holder.e1 = e;
+ rollback();
+ } finally {
+ readerLatch.countDown();
+ }
+ }
+ };
+
+ Thread writer = new Thread() {
+ public void run() {
+ try {
+ BatchModeTransactionManager.getInstance().begin();
+ log.debug("Put value2");
+ region.put(KEY, VALUE2);
+ log.debug("Put finished for value2, await writer latch");
+ writerLatch.await();
+ log.debug("Writer latch finished");
+ BatchModeTransactionManager.getInstance().commit();
+ log.debug("Transaction committed");
+ } catch (Exception e) {
+ holder.e2 = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ reader.setDaemon(true);
+ writer.setDaemon(true);
+
+ writer.start();
+ assertFalse("Writer is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ // Start the reader
+ reader.start();
+ assertTrue("Reader finished promptly", readerLatch.await(1000000000, TimeUnit.MILLISECONDS));
+
+ writerLatch.countDown();
+ assertTrue("Reader finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ assertEquals(VALUE2, region.get(KEY));
+
+ if (holder.a1 != null)
+ throw holder.a1;
+ else if (holder.a2 != null)
+ throw holder.a2;
+
+ assertEquals("writer saw no exceptions", null, holder.e1);
+ assertEquals("reader saw no exceptions", null, holder.e2);
+ }
+
+ public void testGetDoesNotBlockPut() throws Exception {
+ getDoesNotBlockPutTest();
+ }
+
+ // public void testGetDoesNotBlockPutPessimisticRepeatableRead() throws Exception {
+ // getDoesNotBlockPutTest();
+ // }
+
+ private void getDoesNotBlockPutTest() throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(getStandardRegionName(REGION_PREFIX), cfg
+ .getProperties());
+
+ region.put(KEY, VALUE1);
+ assertEquals(VALUE1, region.get(KEY));
+
+ // final Fqn rootFqn = getRegionFqn(getStandardRegionName(REGION_PREFIX), REGION_PREFIX);
+ final Cache jbc = getInfinispanCache(regionFactory);
+
+ final CountDownLatch blockerLatch = new CountDownLatch(1);
+ final CountDownLatch writerLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ final ExceptionHolder holder = new ExceptionHolder();
+
+ Thread blocker = new Thread() {
+
+ public void run() {
+ // Fqn toBlock = new Fqn(rootFqn, KEY);
+ GetBlocker blocker = new GetBlocker(blockerLatch, KEY);
+ try {
+ jbc.addListener(blocker);
+
+ BatchModeTransactionManager.getInstance().begin();
+ region.get(KEY);
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ holder.e1 = e;
+ rollback();
+ } finally {
+ jbc.removeListener(blocker);
+ }
+ }
+ };
+
+ Thread writer = new Thread() {
+
+ public void run() {
+ try {
+ writerLatch.await();
+
+ BatchModeTransactionManager.getInstance().begin();
+ region.put(KEY, VALUE2);
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ holder.e2 = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ blocker.setDaemon(true);
+ writer.setDaemon(true);
+
+ boolean unblocked = false;
+ try {
+ blocker.start();
+ writer.start();
+
+ assertFalse("Blocker is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+ // Start the writer
+ writerLatch.countDown();
+ assertTrue("Writer finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ blockerLatch.countDown();
+ unblocked = true;
+
+ if (IsolationLevel.REPEATABLE_READ.equals(jbc.getConfiguration().getIsolationLevel())) {
+ assertEquals(VALUE1, region.get(KEY));
+ } else {
+ assertEquals(VALUE2, region.get(KEY));
+ }
+
+ if (holder.a1 != null)
+ throw holder.a1;
+ else if (holder.a2 != null)
+ throw holder.a2;
+
+ assertEquals("blocker saw no exceptions", null, holder.e1);
+ assertEquals("writer saw no exceptions", null, holder.e2);
+ } finally {
+ if (!unblocked)
+ blockerLatch.countDown();
+ }
+ }
+
+ @Listener
+ public class GetBlocker {
+
+ private CountDownLatch latch;
+ // private Fqn fqn;
+ private Object key;
+
+ GetBlocker(CountDownLatch latch, Object key) {
+ this.latch = latch;
+ this.key = key;
+ }
+
+ @CacheEntryVisited
+ public void nodeVisisted(CacheEntryVisitedEvent event) {
+ if (event.isPre() && event.getKey().equals(key)) {
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ log.error("Interrupted waiting for latch", e);
+ }
+ }
+ }
+ }
+
+ private class ExceptionHolder {
+ Exception e1;
+ Exception e2;
+ AssertionFailedError a1;
+ AssertionFailedError a2;
+ }
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.hibernate.test.cache.infinispan.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.connection.ConnectionProviderFactory;
+
+/**
+ * XaConnectionProvider.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+public class XaConnectionProvider implements ConnectionProvider {
+ private static ConnectionProvider actualConnectionProvider = ConnectionProviderFactory.newConnectionProvider();
+ private boolean isTransactional;
+
+ public static ConnectionProvider getActualConnectionProvider() {
+ return actualConnectionProvider;
+ }
+
+ public void configure(Properties props) throws HibernateException {
+ }
+
+ public Connection getConnection() throws SQLException {
+ XaTransactionImpl currentTransaction = XaTransactionManagerImpl.getInstance().getCurrentTransaction();
+ if (currentTransaction == null) {
+ isTransactional = false;
+ return actualConnectionProvider.getConnection();
+ } else {
+ isTransactional = true;
+ Connection connection = currentTransaction.getEnlistedConnection();
+ if (connection == null) {
+ connection = actualConnectionProvider.getConnection();
+ currentTransaction.enlistConnection(connection);
+ }
+ return connection;
+ }
+ }
+
+ public void closeConnection(Connection conn) throws SQLException {
+ if (!isTransactional) {
+ conn.close();
+ }
+ }
+
+ public void close() throws HibernateException {
+ actualConnectionProvider.close();
+ }
+
+ public boolean supportsAggressiveRelease() {
+ return true;
+ }
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,247 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.hibernate.test.cache.infinispan.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * XaResourceCapableTransactionImpl.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+public class XaTransactionImpl implements Transaction {
+ private static final Logger log = LoggerFactory.getLogger(XaTransactionImpl.class);
+ private int status;
+ private LinkedList synchronizations;
+ private Connection connection; // the only resource we care about is jdbc connection
+ private final XaTransactionManagerImpl jtaTransactionManager;
+ private List<XAResource> enlistedResources = new ArrayList<XAResource>();
+ private Xid xid = new XaResourceCapableTransactionXid();
+
+ public XaTransactionImpl(XaTransactionManagerImpl jtaTransactionManager) {
+ this.jtaTransactionManager = jtaTransactionManager;
+ this.status = Status.STATUS_ACTIVE;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+ IllegalStateException, SystemException {
+
+ if (status == Status.STATUS_MARKED_ROLLBACK) {
+ log.trace("on commit, status was marked for rollback-only");
+ rollback();
+ } else {
+ status = Status.STATUS_PREPARING;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.beforeCompletion();
+ }
+
+// if (!runXaResourcePrepare()) {
+// status = Status.STATUS_ROLLING_BACK;
+// } else {
+// status = Status.STATUS_PREPARED;
+// }
+
+ status = Status.STATUS_COMMITTING;
+
+ if (connection != null) {
+ try {
+ connection.commit();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+ }
+
+// runXaResourceCommitTx();
+
+ status = Status.STATUS_COMMITTED;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ jtaTransactionManager.endCurrent(this);
+ }
+ }
+
+ public void rollback() throws IllegalStateException, SystemException {
+// status = Status.STATUS_ROLLING_BACK;
+// runXaResourceRollback();
+ status = Status.STATUS_ROLLEDBACK;
+
+ if (connection != null) {
+ try {
+ connection.rollback();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+ }
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ jtaTransactionManager.endCurrent(this);
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ status = Status.STATUS_MARKED_ROLLBACK;
+ }
+
+ public void registerSynchronization(Synchronization synchronization) throws RollbackException,
+ IllegalStateException, SystemException {
+ // todo : find the spec-allowable statuses during which synch can be registered...
+ if (synchronizations == null) {
+ synchronizations = new LinkedList();
+ }
+ synchronizations.add(synchronization);
+ }
+
+ public void enlistConnection(Connection connection) {
+ if (this.connection != null) {
+ throw new IllegalStateException("Connection already registered");
+ }
+ this.connection = connection;
+ }
+
+ public Connection getEnlistedConnection() {
+ return connection;
+ }
+
+ public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException,
+ SystemException {
+ enlistedResources.add(xaResource);
+ try {
+ xaResource.start(xid, 0);
+ } catch (XAException e) {
+ log.error("Got an exception", e);
+ throw new SystemException(e.getMessage());
+ }
+ return true;
+ }
+
+ public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException {
+ throw new SystemException("not supported");
+ }
+
+ public Collection<XAResource> getEnlistedResources() {
+ return enlistedResources;
+ }
+
+ private boolean runXaResourcePrepare() throws SystemException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.prepare(xid);
+ } catch (XAException e) {
+ log.trace("The resource wants to rollback!", e);
+ return false;
+ } catch (Throwable th) {
+ log.error("Unexpected error from resource manager!", th);
+ throw new SystemException(th.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private void runXaResourceRollback() {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.rollback(xid);
+ } catch (XAException e) {
+ log.warn("Error while rolling back",e);
+ }
+ }
+ }
+
+ private boolean runXaResourceCommitTx() throws HeuristicMixedException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.commit(xid, false);//todo we only support one phase commit for now, change this!!!
+ } catch (XAException e) {
+ log.warn("exception while committing",e);
+ throw new HeuristicMixedException(e.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private static class XaResourceCapableTransactionXid implements Xid {
+ private static AtomicInteger txIdCounter = new AtomicInteger(0);
+ private int id = txIdCounter.incrementAndGet();
+
+ public int getFormatId() {
+ return id;
+ }
+
+ public byte[] getGlobalTransactionId() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ public byte[] getBranchQualifier() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" +
+ "id=" + id +
+ '}';
+ }
+ }
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.hibernate.test.cache.infinispan.tm;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.test.tm.SimpleJtaTransactionImpl;
+import org.hibernate.test.tm.SimpleJtaTransactionManagerImpl;
+
+/**
+ * XaResourceCapableTransactionManagerImpl.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+public class XaTransactionManagerImpl implements TransactionManager {
+ private static final XaTransactionManagerImpl INSTANCE = new XaTransactionManagerImpl();
+ private XaTransactionImpl currentTransaction;
+
+ public static XaTransactionManagerImpl getInstance() {
+ return INSTANCE;
+ }
+
+ public int getStatus() throws SystemException {
+ return currentTransaction == null ? Status.STATUS_NO_TRANSACTION : currentTransaction.getStatus();
+ }
+
+ public Transaction getTransaction() throws SystemException {
+ return currentTransaction;
+ }
+
+ public XaTransactionImpl getCurrentTransaction() {
+ return currentTransaction;
+ }
+
+ public void begin() throws NotSupportedException, SystemException {
+ currentTransaction = new XaTransactionImpl(this);
+ }
+
+ public Transaction suspend() throws SystemException {
+ Transaction suspended = currentTransaction;
+ currentTransaction = null;
+ return suspended;
+ }
+
+ public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException,
+ SystemException {
+ currentTransaction = (XaTransactionImpl) transaction;
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+ SecurityException, IllegalStateException, SystemException {
+ if (currentTransaction == null) {
+ throw new IllegalStateException("no current transaction to commit");
+ }
+ currentTransaction.commit();
+ }
+
+ public void rollback() throws IllegalStateException, SecurityException, SystemException {
+ if (currentTransaction == null) {
+ throw new IllegalStateException("no current transaction");
+ }
+ currentTransaction.rollback();
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ if (currentTransaction == null) {
+ throw new IllegalStateException("no current transaction");
+ }
+ currentTransaction.setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int i) throws SystemException {
+ }
+
+ void endCurrent(Transaction transaction) {
+ if (transaction == currentTransaction) {
+ currentTransaction = null;
+ }
+ }
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.hibernate.test.cache.infinispan.tm;
+
+import java.util.Properties;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.HibernateException;
+import org.hibernate.test.tm.SimpleJtaTransactionManagerImpl;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+/**
+ * XaResourceCapableTransactionManagerLookup.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class XaTransactionManagerLookup implements TransactionManagerLookup {
+
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+ public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ return XaTransactionManagerImpl.getInstance();
+ }
+
+ public String getUserTransactionName() {
+ throw new UnsupportedOperationException( "jndi currently not implemented for these tests" );
+ }
+
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,61 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.util;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.Transaction;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Uses the JBoss Cache BatchModeTransactionManager. Should not be used in
+ * any tests that simulate usage of database connections.
+ *
+ * @author Brian Stansberry
+ */
+public class BatchModeTransactionManagerLookup
+ implements TransactionManagerLookup {
+
+ public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ try {
+ return BatchModeTransactionManager.getInstance();
+ }
+ catch (Exception e) {
+ throw new HibernateException("Failed getting BatchModeTransactionManager", e);
+ }
+ }
+
+ public String getUserTransactionName() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+}
Property changes on: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,152 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.slf4j.Logger;
+
+import org.hibernate.cache.RegionFactory;
+import org.infinispan.Cache;
+
+/**
+ * Support class for tracking and cleaning up objects used in tests.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CacheTestSupport {
+
+ private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
+
+ private Logger log;
+
+ private Set<Cache> caches = new HashSet();
+ private Set<RegionFactory> factories = new HashSet();
+ private Exception exception;
+ private String preferIPv4Stack;
+
+ public CacheTestSupport(Logger log) {
+ this.log = log;
+ }
+
+ public void registerCache(Cache cache) {
+ caches.add(cache);
+ }
+
+ public void registerFactory(RegionFactory factory) {
+ factories.add(factory);
+ }
+
+ public void unregisterCache(Cache cache) {
+ caches.remove(cache);
+ }
+
+ public void unregisterFactory(RegionFactory factory) {
+ factories.remove(factory);
+ }
+
+ public void setUp() throws Exception {
+
+ // Try to ensure we use IPv4; otherwise cluster formation is very slow
+ preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
+ System.setProperty(PREFER_IPV4STACK, "true");
+
+ cleanUp();
+ throwStoredException();
+ }
+
+ public void tearDown() throws Exception {
+
+ if (preferIPv4Stack == null)
+ System.clearProperty(PREFER_IPV4STACK);
+ else
+ System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
+
+ cleanUp();
+ throwStoredException();
+ }
+
+ public void avoidConcurrentFlush() {
+ // JG 2.6.1 has a problem where calling flush more than once too quickly
+ // can result in several second delays
+ sleep(100);
+ }
+
+ private void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ }
+ catch (InterruptedException e) {
+ log.warn("Interrupted during sleep", e);
+ }
+ }
+
+ private void cleanUp() {
+ for (Iterator it = factories.iterator(); it.hasNext(); ) {
+ try {
+ ((RegionFactory) it.next()).stop();
+ }
+ catch (Exception e) {
+ storeException(e);
+ }
+ finally {
+ it.remove();
+ }
+ }
+ factories.clear();
+
+ for (Iterator it = caches.iterator(); it.hasNext(); ) {
+ try {
+ Cache cache = (Cache) it.next();
+ cache.stop();
+ }
+ catch (Exception e) {
+ storeException(e);
+ }
+ finally {
+ it.remove();
+ }
+ avoidConcurrentFlush();
+ }
+ caches.clear();
+ }
+
+ private void storeException(Exception e) {
+ if (this.exception == null) {
+ this.exception = e;
+ }
+ }
+
+ private void throwStoredException() throws Exception {
+ if (exception != null) {
+ Exception toThrow = exception;
+ exception = null;
+ throw toThrow;
+ }
+ }
+
+}
Added: core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java
===================================================================
--- core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java (rev 0)
+++ core/branches/INFINISPAN/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java 2009-08-18 19:48:57 UTC (rev 17355)
@@ -0,0 +1,140 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.util;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Utilities for cache testing.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CacheTestUtil {
+
+ public static Configuration buildConfiguration(String regionPrefix, Class regionFactory, boolean use2ndLevel, boolean useQueries) {
+ Configuration cfg = new Configuration();
+ cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
+ cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
+ cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, BatchModeTransactionManagerLookup.class.getName());
+
+ cfg.setProperty(Environment.CACHE_REGION_FACTORY, regionFactory.getName());
+ cfg.setProperty(Environment.CACHE_REGION_PREFIX, regionPrefix);
+ cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, String.valueOf(use2ndLevel));
+ cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(useQueries));
+
+ return cfg;
+ }
+
+ public static Configuration buildLocalOnlyConfiguration(String regionPrefix, boolean use2ndLevel, boolean useQueries) {
+ Configuration cfg = buildConfiguration(regionPrefix, InfinispanRegionFactory.class, use2ndLevel, useQueries);
+ cfg.setProperty(InfinispanRegionFactory.INFINISPAN_CONFIG_RESOURCE_PROP,
+ InfinispanRegionFactory.DEF_INFINISPAN_CONFIG_RESOURCE);
+ return cfg;
+ }
+
+ public static InfinispanRegionFactory startRegionFactory(Configuration cfg) throws ClassNotFoundException,
+ InstantiationException, IllegalAccessException {
+
+ Settings settings = cfg.buildSettings();
+ Properties properties = cfg.getProperties();
+
+ String factoryType = cfg.getProperty(Environment.CACHE_REGION_FACTORY);
+ Class factoryClass = Thread.currentThread().getContextClassLoader().loadClass(factoryType);
+ InfinispanRegionFactory regionFactory = (InfinispanRegionFactory) factoryClass.newInstance();
+
+ regionFactory.start(settings, properties);
+
+ return regionFactory;
+ }
+
+ public static InfinispanRegionFactory startRegionFactory(Configuration cfg, CacheTestSupport testSupport)
+ throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ InfinispanRegionFactory factory = startRegionFactory(cfg);
+ testSupport.registerFactory(factory);
+ return factory;
+ }
+
+ public static void stopRegionFactory(InfinispanRegionFactory factory, CacheTestSupport testSupport) {
+ factory.stop();
+ testSupport.unregisterFactory(factory);
+ }
+
+ /**
+ * Supports easy creation of a TestSuite where a subclass' "FailureExpected" version of a base
+ * test is included in the suite, while the base test is excluded. E.g. test class FooTestCase
+ * includes method testBar(), while test class SubFooTestCase extends FooTestCase includes method
+ * testBarFailureExcluded(). Passing SubFooTestCase.class to this method will return a suite that
+ * does not include testBar().
+ *
+ * FIXME Move this to UnitTestCase
+ */
+ public static TestSuite createFailureExpectedSuite(Class testClass) {
+
+ TestSuite allTests = new TestSuite(testClass);
+ Set failureExpected = new HashSet();
+ Enumeration tests = allTests.tests();
+ while (tests.hasMoreElements()) {
+ Test t = (Test) tests.nextElement();
+ if (t instanceof TestCase) {
+ String name = ((TestCase) t).getName();
+ if (name.endsWith("FailureExpected"))
+ failureExpected.add(name);
+ }
+ }
+
+ TestSuite result = new TestSuite();
+ tests = allTests.tests();
+ while (tests.hasMoreElements()) {
+ Test t = (Test) tests.nextElement();
+ if (t instanceof TestCase) {
+ String name = ((TestCase) t).getName();
+ if (!failureExpected.contains(name + "FailureExpected")) {
+ result.addTest(t);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Prevent instantiation.
+ */
+ private CacheTestUtil() {
+ }
+
+}
More information about the hibernate-commits
mailing list