HHH-6297 remove legacy cache api
This commit is contained in:
parent
ad180ff95a
commit
92ad3eed80
|
@ -750,9 +750,9 @@ Customer customer = (Customer) session.get( Customer.class, customerId );
|
|||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Hashtable (not intended for production use)</entry>
|
||||
<entry>ConcurrentHashMap (only for testing purpose, in hibernate-testing module)</entry>
|
||||
|
||||
<entry><literal>org.hibernate.cache.internal.HashtableCacheProvider</literal></entry>
|
||||
<entry><literal>org.hibernate.testing.cache.CachingRegionFactory</literal></entry>
|
||||
|
||||
<entry>memory</entry>
|
||||
|
||||
|
@ -764,7 +764,7 @@ Customer customer = (Customer) session.get( Customer.class, customerId );
|
|||
<row>
|
||||
<entry>EHCache</entry>
|
||||
|
||||
<entry><literal>org.hibernate.cache.internal.EhCacheProvider</literal></entry>
|
||||
<entry><literal>org.hibernate.cache.internal.EhCacheRegionFactory</literal></entry>
|
||||
|
||||
<entry>memory, disk</entry>
|
||||
|
||||
|
@ -773,7 +773,7 @@ Customer customer = (Customer) session.get( Customer.class, customerId );
|
|||
<entry>yes</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<!-- <row>
|
||||
<entry>OSCache</entry>
|
||||
|
||||
<entry><literal>org.hibernate.cache.OSCacheProvider</literal></entry>
|
||||
|
@ -818,6 +818,17 @@ Customer customer = (Customer) session.get( Customer.class, customerId );
|
|||
|
||||
<entry>yes (replication or invalidation)</entry>
|
||||
|
||||
<entry>yes (clock sync req.)</entry>
|
||||
</row> -->
|
||||
<row>
|
||||
<entry>Infinispan</entry>
|
||||
|
||||
<entry><literal>org.hibernate.cache.infinispan.InfinispanRegionFactory</literal></entry>
|
||||
|
||||
<entry>clustered (ip multicast), transactional</entry>
|
||||
|
||||
<entry>yes (replication or invalidation)</entry>
|
||||
|
||||
<entry>yes (clock sync req.)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
|
@ -1114,7 +1125,7 @@ public SortedSet<Ticket> getTickets() {
|
|||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Hashtable (not intended for production use)</entry>
|
||||
<entry>ConcurrentHashMap (not intended for production use)</entry>
|
||||
|
||||
<entry>yes</entry>
|
||||
|
||||
|
@ -1134,10 +1145,10 @@ public SortedSet<Ticket> getTickets() {
|
|||
|
||||
<entry>yes</entry>
|
||||
|
||||
<entry></entry>
|
||||
<entry>yes</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<!-- <row>
|
||||
<entry>OSCache</entry>
|
||||
|
||||
<entry>yes</entry>
|
||||
|
@ -1182,6 +1193,17 @@ public SortedSet<Ticket> getTickets() {
|
|||
|
||||
<entry></entry>
|
||||
|
||||
<entry>yes</entry>
|
||||
</row> -->
|
||||
<row>
|
||||
<entry>Infinispan</entry>
|
||||
|
||||
<entry>yes</entry>
|
||||
|
||||
<entry></entry>
|
||||
|
||||
<entry></entry>
|
||||
|
||||
<entry>yes</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
|
|
|
@ -492,13 +492,11 @@ hibernate.cache.region_prefix hibernate.test
|
|||
|
||||
## choose a cache implementation
|
||||
|
||||
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
|
||||
hibernate.cache.provider_class org.hibernate.cache.internal.HashtableCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
|
||||
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.infinispan.InfinispanRegionFactory
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.infinispan.JndiInfinispanRegionFactory
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.internal.EhCacheRegionFactory
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.internal.SingletonEhCacheRegionFactory
|
||||
hibernate.cache.region.factory_class org.hibernate.cache.internal.NoCachingRegionFactory
|
||||
|
||||
## choose a custom query cache implementation
|
||||
|
||||
|
|
|
@ -451,12 +451,11 @@ hibernate.cache.region_prefix hibernate.test
|
|||
|
||||
## choose a cache implementation
|
||||
|
||||
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
|
||||
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
|
||||
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.infinispan.InfinispanRegionFactory
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.infinispan.JndiInfinispanRegionFactory
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.internal.EhCacheRegionFactory
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.internal.SingletonEhCacheRegionFactory
|
||||
#hibernate.cache.region.factory_class org.hibernate.cache.internal.NoCachingRegionFactory
|
||||
|
||||
|
||||
## choose a custom query cache implementation
|
||||
|
|
|
@ -25,7 +25,10 @@ package org.hibernate;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* Describes the methods for multi-tenancy understood by Hibernate.
|
||||
|
@ -33,6 +36,7 @@ import org.hibernate.cfg.Environment;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum MultiTenancyStrategy {
|
||||
|
||||
/**
|
||||
* Multi-tenancy implemented by use of discriminator columns.
|
||||
*/
|
||||
|
@ -49,7 +53,10 @@ public enum MultiTenancyStrategy {
|
|||
* No multi-tenancy
|
||||
*/
|
||||
NONE;
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
MultiTenancyStrategy.class.getName()
|
||||
);
|
||||
public static MultiTenancyStrategy determineMultiTenancyStrategy(Map properties) {
|
||||
final Object strategy = properties.get( Environment.MULTI_TENANT );
|
||||
if ( strategy == null ) {
|
||||
|
@ -61,20 +68,11 @@ public enum MultiTenancyStrategy {
|
|||
}
|
||||
|
||||
final String strategyName = strategy.toString();
|
||||
if ( MultiTenancyStrategy.DISCRIMINATOR.name().equals( strategyName ) ) {
|
||||
return MultiTenancyStrategy.DISCRIMINATOR;
|
||||
try {
|
||||
return MultiTenancyStrategy.valueOf( strategyName.toUpperCase() );
|
||||
}
|
||||
else if ( MultiTenancyStrategy.SCHEMA.name().equals( strategyName ) ) {
|
||||
return MultiTenancyStrategy.SCHEMA;
|
||||
}
|
||||
else if ( MultiTenancyStrategy.DATABASE.name().equals( strategyName ) ) {
|
||||
return MultiTenancyStrategy.DATABASE;
|
||||
}
|
||||
else if ( MultiTenancyStrategy.NONE.name().equals( strategyName ) ) {
|
||||
return MultiTenancyStrategy.NONE;
|
||||
}
|
||||
else {
|
||||
// todo log?
|
||||
catch ( RuntimeException e ) {
|
||||
LOG.warn( "Unknown multi tenancy strategy [ " +strategyName +" ], using MultiTenancyStrategy.NONE." );
|
||||
return MultiTenancyStrategy.NONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
|
||||
/**
|
||||
* A lightweight implementation of the <tt>Cache</tt> interface
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class HashtableCache implements Cache {
|
||||
|
||||
private final Map hashtable = new Hashtable();
|
||||
private final String regionName;
|
||||
|
||||
public HashtableCache(String regionName) {
|
||||
this.regionName = regionName;
|
||||
}
|
||||
|
||||
public String getRegionName() {
|
||||
return regionName;
|
||||
}
|
||||
|
||||
public Object read(Object key) throws CacheException {
|
||||
return hashtable.get(key);
|
||||
}
|
||||
|
||||
public Object get(Object key) throws CacheException {
|
||||
return hashtable.get(key);
|
||||
}
|
||||
|
||||
public void update(Object key, Object value) throws CacheException {
|
||||
put(key, value);
|
||||
}
|
||||
|
||||
public void put(Object key, Object value) throws CacheException {
|
||||
hashtable.put(key, value);
|
||||
}
|
||||
|
||||
public void remove(Object key) throws CacheException {
|
||||
hashtable.remove(key);
|
||||
}
|
||||
|
||||
public void clear() throws CacheException {
|
||||
hashtable.clear();
|
||||
}
|
||||
|
||||
public void destroy() throws CacheException {
|
||||
|
||||
}
|
||||
|
||||
public void lock(Object key) throws CacheException {
|
||||
// local cache, so we use synchronization
|
||||
}
|
||||
|
||||
public void unlock(Object key) throws CacheException {
|
||||
// local cache, so we use synchronization
|
||||
}
|
||||
|
||||
public long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return Timestamper.ONE_MS * 60000; //ie. 60 seconds
|
||||
}
|
||||
|
||||
public long getSizeInMemory() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public long getElementCountInMemory() {
|
||||
return hashtable.size();
|
||||
}
|
||||
|
||||
public long getElementCountOnDisk() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Map toMap() {
|
||||
return Collections.unmodifiableMap(hashtable);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "HashtableCache(" + regionName + ')';
|
||||
}
|
||||
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.NoCachingEnabledException;
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.CacheProvider;
|
||||
|
||||
/**
|
||||
* Implementation of NoCacheProvider.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Deprecated
|
||||
public class NoCacheProvider implements CacheProvider {
|
||||
/**
|
||||
* Configure the cache
|
||||
*
|
||||
* @param regionName the name of the cache region
|
||||
* @param properties configuration settings
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException
|
||||
*/
|
||||
public Cache buildCache(String regionName, Properties properties) throws CacheException {
|
||||
throw new NoCachingEnabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a timestamp
|
||||
*/
|
||||
public long nextTimestamp() {
|
||||
// This, is used by SessionFactoryImpl to hand to the generated SessionImpl;
|
||||
// was the only reason I could see that we cannot just use null as
|
||||
// Settings.cacheProvider
|
||||
return System.currentTimeMillis() / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary initialization of the underlying cache implementation during SessionFactory
|
||||
* construction.
|
||||
*
|
||||
* @param properties current configuration settings.
|
||||
*/
|
||||
public void start(Properties properties) throws CacheException {
|
||||
// this is called by SessionFactory irregardless; we just disregard here;
|
||||
// could also add a check to SessionFactory to only conditionally call start
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary cleanup of the underlying cache implementation during SessionFactory.close().
|
||||
*/
|
||||
public void stop() {
|
||||
// this is called by SessionFactory irregardless; we just disregard here;
|
||||
// could also add a check to SessionFactory to only conditionally call stop
|
||||
}
|
||||
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
// this is called from SettingsFactory irregardless; trivial to simply disregard
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,29 +23,28 @@
|
|||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Generates increasing identifiers (in a single VM only). Not valid across multiple VMs. Identifiers are not
|
||||
* necessarily strictly increasing, but usually are.
|
||||
*/
|
||||
public final class Timestamper {
|
||||
private static short counter = 0;
|
||||
private static long time;
|
||||
private static final int BIN_DIGITS = 12;
|
||||
public static final short ONE_MS = 1<<BIN_DIGITS;
|
||||
|
||||
private static final AtomicLong VALUE = new AtomicLong();
|
||||
public static long next() {
|
||||
synchronized(Timestamper.class) {
|
||||
long newTime = System.currentTimeMillis() << BIN_DIGITS;
|
||||
if (time<newTime) {
|
||||
time = newTime;
|
||||
counter = 0;
|
||||
}
|
||||
else if (counter < ONE_MS - 1 ) {
|
||||
counter++;
|
||||
}
|
||||
while (true) {
|
||||
long base = System.currentTimeMillis() << BIN_DIGITS;
|
||||
long maxValue = base + ONE_MS - 1;
|
||||
|
||||
return time + counter;
|
||||
}
|
||||
for (long current = VALUE.get(), update = Math.max(base, current + 1); update < maxValue;
|
||||
current = VALUE.get(), update = Math.max(base, current + 1)) {
|
||||
if (VALUE.compareAndSet(current, update)) {
|
||||
return update;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Timestamper() {
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal.bridge;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.CacheConcurrencyStrategy;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Adapter specifically bridging {@link CollectionRegionAccessStrategy} to {@link CacheConcurrencyStrategy}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CollectionAccessStrategyAdapter implements CollectionRegionAccessStrategy {
|
||||
private final CollectionRegion region;
|
||||
private final CacheConcurrencyStrategy ccs;
|
||||
private final Settings settings;
|
||||
|
||||
public CollectionAccessStrategyAdapter(CollectionRegion region, CacheConcurrencyStrategy ccs, Settings settings) {
|
||||
this.region = region;
|
||||
this.ccs = ccs;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public CollectionRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public Object get(Object key, long txTimestamp) throws CacheException {
|
||||
return ccs.get( key, txTimestamp );
|
||||
}
|
||||
|
||||
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
|
||||
return putFromLoad( key, value, txTimestamp, version, settings.isMinimalPutsEnabled() );
|
||||
}
|
||||
|
||||
public boolean putFromLoad(
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version,
|
||||
boolean minimalPutOverride) throws CacheException {
|
||||
return ccs.put( key, value, txTimestamp, version, region.getCacheDataDescription().getVersionComparator(), minimalPutOverride );
|
||||
}
|
||||
|
||||
public SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
return ccs.lock( key, version );
|
||||
}
|
||||
|
||||
public SoftLock lockRegion() throws CacheException {
|
||||
// no-op; CCS did not have such a concept
|
||||
return null;
|
||||
}
|
||||
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
ccs.release( key, lock );
|
||||
}
|
||||
|
||||
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||
// again, CCS did not have such a concept; but a reasonable
|
||||
// proximity is to clear the cache after transaction *as long as*
|
||||
// the underlying cache is not JTA aware.
|
||||
if ( !region.isTransactionAware() ) {
|
||||
ccs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(Object key) throws CacheException {
|
||||
ccs.evict( key );
|
||||
}
|
||||
|
||||
public void removeAll() throws CacheException {
|
||||
// again, CCS did not have such a concept; however a reasonable
|
||||
// proximity is to clear the cache. For non-transaction aware
|
||||
// caches, we will also do a clear at the end of the transaction
|
||||
ccs.clear();
|
||||
}
|
||||
|
||||
public void evict(Object key) throws CacheException {
|
||||
ccs.remove( key );
|
||||
}
|
||||
|
||||
public void evictAll() throws CacheException {
|
||||
ccs.clear();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
ccs.destroy();
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal.bridge;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.CacheConcurrencyStrategy;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.NonstrictReadWriteCache;
|
||||
import org.hibernate.cache.spi.OptimisticCache;
|
||||
import org.hibernate.cache.spi.ReadOnlyCache;
|
||||
import org.hibernate.cache.spi.ReadWriteCache;
|
||||
import org.hibernate.cache.spi.TransactionalCache;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* Adapter specifically bridging {@link CollectionRegion} to {@link Cache}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CollectionRegionAdapter extends BaseTransactionalDataRegionAdapter implements CollectionRegion {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
||||
CollectionRegionAdapter.class.getName());
|
||||
|
||||
public CollectionRegionAdapter(Cache underlyingCache, Settings settings, CacheDataDescription metadata) {
|
||||
super( underlyingCache, settings, metadata );
|
||||
if ( underlyingCache instanceof OptimisticCache ) {
|
||||
( ( OptimisticCache ) underlyingCache ).setSource( new OptimisticCacheSourceAdapter( metadata ) );
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
CacheConcurrencyStrategy ccs;
|
||||
if ( AccessType.READ_ONLY.equals( accessType ) ) {
|
||||
if (metadata.isMutable()) LOG.readOnlyCacheConfiguredForMutableCollection(getName());
|
||||
ccs = new ReadOnlyCache();
|
||||
}
|
||||
else if ( AccessType.READ_WRITE.equals( accessType ) ) {
|
||||
ccs = new ReadWriteCache();
|
||||
}
|
||||
else if ( AccessType.NONSTRICT_READ_WRITE.equals( accessType ) ) {
|
||||
ccs = new NonstrictReadWriteCache();
|
||||
}
|
||||
else if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
|
||||
ccs = new TransactionalCache();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
}
|
||||
ccs.setCache( underlyingCache );
|
||||
return new CollectionAccessStrategyAdapter( this, ccs, settings );
|
||||
}
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal.bridge;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.CacheConcurrencyStrategy;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Adapter specifically bridging {@link EntityRegionAccessStrategy} to {@link CacheConcurrencyStrategy}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityAccessStrategyAdapter implements EntityRegionAccessStrategy {
|
||||
private final EntityRegion region;
|
||||
private final CacheConcurrencyStrategy ccs;
|
||||
private final Settings settings;
|
||||
|
||||
public EntityAccessStrategyAdapter(EntityRegion region, CacheConcurrencyStrategy ccs, Settings settings) {
|
||||
this.region = region;
|
||||
this.ccs = ccs;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public EntityRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public Object get(Object key, long txTimestamp) throws CacheException {
|
||||
return ccs.get( key, txTimestamp );
|
||||
}
|
||||
|
||||
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
|
||||
return putFromLoad( key, value, txTimestamp, version, settings.isMinimalPutsEnabled() );
|
||||
}
|
||||
|
||||
public boolean putFromLoad(
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version,
|
||||
boolean minimalPutOverride) throws CacheException {
|
||||
return ccs.put( key, value, txTimestamp, version, region.getCacheDataDescription().getVersionComparator(), minimalPutOverride );
|
||||
}
|
||||
|
||||
public SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
return ccs.lock( key, version );
|
||||
}
|
||||
|
||||
public SoftLock lockRegion() throws CacheException {
|
||||
// no-op; CCS did not have such a concept
|
||||
return null;
|
||||
}
|
||||
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
ccs.release( key, lock );
|
||||
}
|
||||
|
||||
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||
// again, CCS did not have such a concept; but a reasonable
|
||||
// proximity is to clear the cache after transaction *as long as*
|
||||
// the underlying cache is not JTA aware.
|
||||
if ( !region.isTransactionAware() ) {
|
||||
ccs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean insert(Object key, Object value, Object version) throws CacheException {
|
||||
return ccs.insert( key, value, version );
|
||||
}
|
||||
|
||||
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
|
||||
return ccs.afterInsert( key, value, version );
|
||||
}
|
||||
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
|
||||
throws CacheException {
|
||||
return ccs.update( key, value, currentVersion, previousVersion );
|
||||
}
|
||||
|
||||
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||
throws CacheException {
|
||||
return ccs.afterUpdate( key, value, currentVersion, lock );
|
||||
}
|
||||
|
||||
public void remove(Object key) throws CacheException {
|
||||
ccs.evict( key );
|
||||
}
|
||||
|
||||
public void removeAll() throws CacheException {
|
||||
// again, CCS did not have such a concept; however a reasonable
|
||||
// proximity is to clear the cache. For non-transaction aware
|
||||
// caches, we will also do a clear at the end of the transaction
|
||||
ccs.clear();
|
||||
}
|
||||
|
||||
public void evict(Object key) throws CacheException {
|
||||
ccs.remove( key );
|
||||
}
|
||||
|
||||
public void evictAll() throws CacheException {
|
||||
ccs.clear();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
ccs.destroy();
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal.bridge;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.CacheConcurrencyStrategy;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.NonstrictReadWriteCache;
|
||||
import org.hibernate.cache.spi.OptimisticCache;
|
||||
import org.hibernate.cache.spi.ReadOnlyCache;
|
||||
import org.hibernate.cache.spi.ReadWriteCache;
|
||||
import org.hibernate.cache.spi.TransactionalCache;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* Adapter specifically bridging {@link EntityRegion} to {@link org.hibernate.cache.spi.Cache}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityRegionAdapter extends BaseTransactionalDataRegionAdapter implements EntityRegion {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, EntityRegionAdapter.class.getName());
|
||||
|
||||
public EntityRegionAdapter(Cache underlyingCache, Settings settings, CacheDataDescription metadata) {
|
||||
super( underlyingCache, settings, metadata );
|
||||
if ( underlyingCache instanceof OptimisticCache ) {
|
||||
( (OptimisticCache) underlyingCache ).setSource( new OptimisticCacheSourceAdapter( metadata ) );
|
||||
}
|
||||
}
|
||||
|
||||
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
CacheConcurrencyStrategy ccs;
|
||||
if ( AccessType.READ_ONLY.equals( accessType ) ) {
|
||||
if (metadata.isMutable()) LOG.readOnlyCacheConfiguredForMutableCollection(getName());
|
||||
ccs = new ReadOnlyCache();
|
||||
}
|
||||
else if ( AccessType.READ_WRITE.equals( accessType ) ) {
|
||||
ccs = new ReadWriteCache();
|
||||
}
|
||||
else if ( AccessType.NONSTRICT_READ_WRITE.equals( accessType ) ) {
|
||||
ccs = new NonstrictReadWriteCache();
|
||||
}
|
||||
else if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
|
||||
ccs = new TransactionalCache();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
}
|
||||
ccs.setCache( underlyingCache );
|
||||
return new EntityAccessStrategyAdapter( this, ccs, settings );
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal.bridge;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.internal.NoCacheProvider;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CacheProvider;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
/**
|
||||
* Acts as a bridge between the {@link RegionFactory} contract and the older
|
||||
* {@link CacheProvider} contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class RegionFactoryCacheProviderBridge implements RegionFactory {
|
||||
public static final String DEF_PROVIDER = NoCacheProvider.class.getName();
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
||||
RegionFactoryCacheProviderBridge.class.getName());
|
||||
|
||||
private CacheProvider cacheProvider;
|
||||
private Settings settings;
|
||||
|
||||
public RegionFactoryCacheProviderBridge(Properties properties) {
|
||||
String providerClassName = ConfigurationHelper.getString( Environment.CACHE_PROVIDER, properties, DEF_PROVIDER );
|
||||
LOG.cacheProvider(providerClassName);
|
||||
try {
|
||||
cacheProvider = ( CacheProvider ) ReflectHelper.classForName( providerClassName ).newInstance();
|
||||
}
|
||||
catch ( Exception cnfe ) {
|
||||
throw new CacheException( "could not instantiate CacheProvider [" + providerClassName + "]", cnfe );
|
||||
}
|
||||
}
|
||||
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
this.settings = settings;
|
||||
cacheProvider.start( properties );
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
cacheProvider.stop();
|
||||
cacheProvider = null;
|
||||
}
|
||||
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return cacheProvider.isMinimalPutsEnabledByDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public AccessType getDefaultAccessType() {
|
||||
// we really have no idea
|
||||
return null;
|
||||
}
|
||||
|
||||
public long nextTimestamp() {
|
||||
return cacheProvider.nextTimestamp();
|
||||
}
|
||||
|
||||
public CacheProvider getCacheProvider() {
|
||||
return cacheProvider;
|
||||
}
|
||||
|
||||
public EntityRegion buildEntityRegion(
|
||||
String regionName,
|
||||
Properties properties,
|
||||
CacheDataDescription metadata) throws CacheException {
|
||||
return new EntityRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings, metadata );
|
||||
}
|
||||
|
||||
public CollectionRegion buildCollectionRegion(
|
||||
String regionName,
|
||||
Properties properties,
|
||||
CacheDataDescription metadata) throws CacheException {
|
||||
return new CollectionRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings, metadata );
|
||||
}
|
||||
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new QueryResultsRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings );
|
||||
}
|
||||
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new TimestampsRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal.bridge;
|
||||
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Adapter specifically bridging {@link TimestampsRegion} to {@link org.hibernate.cache.spi.Cache}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TimestampsRegionAdapter extends BaseGeneralDataRegionAdapter implements TimestampsRegion {
|
||||
protected TimestampsRegionAdapter(Cache underlyingCache, Settings settings) {
|
||||
super( underlyingCache, settings );
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.util.Properties;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.jndi.JndiHelper;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Support for CacheProvider implementations which are backed by caches bound
|
||||
* into JNDI namespace.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractJndiBoundCacheProvider implements CacheProvider {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
||||
AbstractJndiBoundCacheProvider.class.getName());
|
||||
|
||||
private Object cache;
|
||||
|
||||
protected void prepare(Properties properties) {
|
||||
// Do nothing; subclasses may override.
|
||||
}
|
||||
|
||||
protected void release() {
|
||||
// Do nothing; subclasses may override.
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary initialization of the underlying cache implementation during SessionFactory
|
||||
* construction.
|
||||
*
|
||||
* @param properties current configuration settings.
|
||||
*/
|
||||
public final void start(Properties properties) throws CacheException {
|
||||
String jndiNamespace = properties.getProperty( Environment.CACHE_NAMESPACE );
|
||||
if ( StringHelper.isEmpty( jndiNamespace ) ) {
|
||||
throw new CacheException( "No JNDI namespace specified for cache" );
|
||||
}
|
||||
cache = locateCache( jndiNamespace, JndiHelper.extractJndiProperties( properties ) );
|
||||
prepare( properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary cleanup of the underlying cache
|
||||
* implementation during SessionFactory.close().
|
||||
*/
|
||||
public final void stop() {
|
||||
release();
|
||||
cache = null;
|
||||
}
|
||||
|
||||
private Object locateCache(String jndiNamespace, Properties jndiProperties) {
|
||||
|
||||
Context ctx = null;
|
||||
try {
|
||||
ctx = new InitialContext( jndiProperties );
|
||||
return ctx.lookup( jndiNamespace );
|
||||
}
|
||||
catch (NamingException ne) {
|
||||
String msg = "Unable to retreive Cache from JNDI [" + jndiNamespace + "]";
|
||||
LOG.unableToRetrieveCache(jndiNamespace, ne.getMessage());
|
||||
throw new CacheException( msg );
|
||||
}
|
||||
finally {
|
||||
if ( ctx != null ) {
|
||||
try {
|
||||
ctx.close();
|
||||
}
|
||||
catch( NamingException ne ) {
|
||||
LOG.unableToReleaseContext(ne.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object getCache() {
|
||||
return cache;
|
||||
}
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
|
||||
/**
|
||||
* Implementors define a caching algorithm. All implementors
|
||||
* <b>must</b> be threadsafe.
|
||||
*
|
||||
* @deprecated As of 3.3; see <a href="package.html"/> for details.
|
||||
*/
|
||||
public interface Cache {
|
||||
/**
|
||||
* Get an item from the cache
|
||||
* @param key
|
||||
* @return the cached object or <tt>null</tt>
|
||||
* @throws org.hibernate.cache.CacheException
|
||||
*/
|
||||
public Object read(Object key) throws CacheException;
|
||||
/**
|
||||
* Get an item from the cache, nontransactionally
|
||||
* @param key
|
||||
* @return the cached object or <tt>null</tt>
|
||||
* @throws CacheException
|
||||
*/
|
||||
public Object get(Object key) throws CacheException;
|
||||
/**
|
||||
* Add an item to the cache, nontransactionally, with
|
||||
* failfast semantics
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void put(Object key, Object value) throws CacheException;
|
||||
/**
|
||||
* Add an item to the cache
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void update(Object key, Object value) throws CacheException;
|
||||
/**
|
||||
* Remove an item from the cache
|
||||
*/
|
||||
public void remove(Object key) throws CacheException;
|
||||
/**
|
||||
* Clear the cache
|
||||
*/
|
||||
public void clear() throws CacheException;
|
||||
/**
|
||||
* Clean up
|
||||
*/
|
||||
public void destroy() throws CacheException;
|
||||
/**
|
||||
* If this is a clustered cache, lock the item
|
||||
*/
|
||||
public void lock(Object key) throws CacheException;
|
||||
/**
|
||||
* If this is a clustered cache, unlock the item
|
||||
*/
|
||||
public void unlock(Object key) throws CacheException;
|
||||
/**
|
||||
* Generate a timestamp
|
||||
*/
|
||||
public long nextTimestamp();
|
||||
/**
|
||||
* Get a reasonable "lock timeout"
|
||||
*/
|
||||
public int getTimeout();
|
||||
|
||||
/**
|
||||
* Get the name of the cache region
|
||||
*/
|
||||
public String getRegionName();
|
||||
|
||||
/**
|
||||
* The number of bytes is this cache region currently consuming in memory.
|
||||
*
|
||||
* @return The number of bytes consumed by this region; -1 if unknown or
|
||||
* unsupported.
|
||||
*/
|
||||
public long getSizeInMemory();
|
||||
|
||||
/**
|
||||
* The count of entries currently contained in the regions in-memory store.
|
||||
*
|
||||
* @return The count of entries in memory; -1 if unknown or unsupported.
|
||||
*/
|
||||
public long getElementCountInMemory();
|
||||
|
||||
/**
|
||||
* The count of entries currently contained in the regions disk store.
|
||||
*
|
||||
* @return The count of entries on disk; -1 if unknown or unsupported.
|
||||
*/
|
||||
public long getElementCountOnDisk();
|
||||
|
||||
/**
|
||||
* optional operation
|
||||
*/
|
||||
public Map toMap();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
||||
/**
|
||||
* Implementors manage transactional access to cached data. Transactions
|
||||
* pass in a timestamp indicating transaction start time. Two different
|
||||
* implementation patterns are provided for.<ul>
|
||||
* <li>A transaction-aware cache implementation might be wrapped by a
|
||||
* "synchronous" concurrency strategy, where updates to the cache are written
|
||||
* to the cache inside the transaction.</li>
|
||||
* <li>A non transaction-aware cache would be wrapped by an "asynchronous"
|
||||
* concurrency strategy, where items are merely "soft locked" during the
|
||||
* transaction and then updated during the "after transaction completion"
|
||||
* phase; the soft lock is not an actual lock on the database row -
|
||||
* only upon the cached representation of the item.</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* In terms of entity caches, the expected call sequences are: <ul>
|
||||
* <li><b>DELETES</b> : {@link #lock} -> {@link #evict} -> {@link #release}</li>
|
||||
* <li><b>UPDATES</b> : {@link #lock} -> {@link #update} -> {@link #afterUpdate}</li>
|
||||
* <li><b>INSERTS</b> : {@link #insert} -> {@link #afterInsert}</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* In terms of collection caches, all modification actions actually just
|
||||
* invalidate the entry(s). The call sequence here is:
|
||||
* {@link #lock} -> {@link #evict} -> {@link #release}
|
||||
* <p/>
|
||||
* Note that, for an asynchronous cache, cache invalidation must be a two
|
||||
* step process (lock->release, or lock-afterUpdate), since this is the only
|
||||
* way to guarantee consistency with the database for a nontransactional cache
|
||||
* implementation. For a synchronous cache, cache invalidation is a single
|
||||
* step process (evict, or update). Hence, this interface defines a three
|
||||
* step process, to cater for both models.
|
||||
* <p/>
|
||||
* Note that query result caching does not go through a concurrency strategy; they
|
||||
* are managed directly against the underlying {@link Cache cache regions}.
|
||||
*
|
||||
* @deprecated As of 3.3; see <a href="package.html"/> for details.
|
||||
*/
|
||||
public interface CacheConcurrencyStrategy {
|
||||
|
||||
/**
|
||||
* Attempt to retrieve an object from the cache. Mainly used in attempting
|
||||
* to resolve entities/collections from the second level cache.
|
||||
*
|
||||
* @param key
|
||||
* @param txTimestamp a timestamp prior to the transaction start time
|
||||
* @return the cached object or <tt>null</tt>
|
||||
* @throws org.hibernate.cache.CacheException
|
||||
*/
|
||||
public Object get(Object key, long txTimestamp) throws CacheException;
|
||||
|
||||
/**
|
||||
* Attempt to cache an object, after loading from the database.
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param txTimestamp a timestamp prior to the transaction start time
|
||||
* @param version the item version number
|
||||
* @param versionComparator a comparator used to compare version numbers
|
||||
* @param minimalPut indicates that the cache should avoid a put is the item is already cached
|
||||
* @return <tt>true</tt> if the object was successfully cached
|
||||
* @throws CacheException
|
||||
*/
|
||||
public boolean put(
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version,
|
||||
Comparator versionComparator,
|
||||
boolean minimalPut)
|
||||
throws CacheException;
|
||||
|
||||
/**
|
||||
* We are going to attempt to update/delete the keyed object. This
|
||||
* method is used by "asynchronous" concurrency strategies.
|
||||
* <p/>
|
||||
* The returned object must be passed back to release(), to release the
|
||||
* lock. Concurrency strategies which do not support client-visible
|
||||
* locks may silently return null.
|
||||
*
|
||||
* @param key
|
||||
* @param version
|
||||
* @throws CacheException
|
||||
*/
|
||||
public SoftLock lock(Object key, Object version) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has become stale (before the transaction completes).
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*/
|
||||
public void evict(Object key) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has been updated (before the transaction completes),
|
||||
* instead of calling evict().
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*/
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has been inserted (before the transaction completes),
|
||||
* instead of calling evict().
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*/
|
||||
public boolean insert(Object key, Object value, Object currentVersion) throws CacheException;
|
||||
|
||||
|
||||
/**
|
||||
* Called when we have finished the attempted update/delete (which may or
|
||||
* may not have been successful), after transaction completion.
|
||||
* This method is used by "asynchronous" concurrency strategies.
|
||||
* @param key
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void release(Object key, SoftLock lock) throws CacheException;
|
||||
/**
|
||||
* Called after an item has been updated (after the transaction completes),
|
||||
* instead of calling release().
|
||||
* This method is used by "asynchronous" concurrency strategies.
|
||||
*/
|
||||
public boolean afterUpdate(Object key, Object value, Object version, SoftLock lock)
|
||||
throws CacheException;
|
||||
/**
|
||||
* Called after an item has been inserted (after the transaction completes),
|
||||
* instead of calling release().
|
||||
* This method is used by "asynchronous" concurrency strategies.
|
||||
*/
|
||||
public boolean afterInsert(Object key, Object value, Object version)
|
||||
throws CacheException;
|
||||
|
||||
|
||||
/**
|
||||
* Evict an item from the cache immediately (without regard for transaction
|
||||
* isolation).
|
||||
* @param key
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void remove(Object key) throws CacheException;
|
||||
/**
|
||||
* Evict all items from the cache immediately.
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void clear() throws CacheException;
|
||||
/**
|
||||
* Clean up all resources.
|
||||
*/
|
||||
public void destroy();
|
||||
/**
|
||||
* Set the underlying cache implementation.
|
||||
* @param cache
|
||||
*/
|
||||
public void setCache(Cache cache);
|
||||
|
||||
/**
|
||||
* Get the cache region name
|
||||
*/
|
||||
public String getRegionName();
|
||||
|
||||
/**
|
||||
* Get the wrapped cache implementation
|
||||
*/
|
||||
public Cache getCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
|
||||
/**
|
||||
* Support for pluggable caches.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @deprecated As of 3.3; see <a href="package.html"/> for details.
|
||||
*/
|
||||
public interface CacheProvider {
|
||||
|
||||
/**
|
||||
* Configure the cache
|
||||
*
|
||||
* @param regionName the name of the cache region
|
||||
* @param properties configuration settings
|
||||
* @throws org.hibernate.cache.CacheException
|
||||
*/
|
||||
public Cache buildCache(String regionName, Properties properties) throws CacheException;
|
||||
|
||||
/**
|
||||
* Generate a timestamp
|
||||
*/
|
||||
public long nextTimestamp();
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary initialization of the underlying cache implementation
|
||||
* during SessionFactory construction.
|
||||
*
|
||||
* @param properties current configuration settings.
|
||||
*/
|
||||
public void start(Properties properties) throws CacheException;
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary cleanup of the underlying cache implementation
|
||||
* during SessionFactory.close().
|
||||
*/
|
||||
public void stop();
|
||||
|
||||
public boolean isMinimalPutsEnabledByDefault();
|
||||
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* Caches data that is sometimes updated without ever locking the cache.
|
||||
* If concurrent access to an item is possible, this concurrency strategy
|
||||
* makes no guarantee that the item returned from the cache is the latest
|
||||
* version available in the database. Configure your cache timeout accordingly!
|
||||
* This is an "asynchronous" concurrency strategy.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @see ReadWriteCache for a much stricter algorithm
|
||||
*/
|
||||
@Deprecated
|
||||
public class NonstrictReadWriteCache implements CacheConcurrencyStrategy {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
||||
NonstrictReadWriteCache.class.getName());
|
||||
|
||||
private Cache cache;
|
||||
|
||||
public NonstrictReadWriteCache() {
|
||||
}
|
||||
|
||||
public void setCache(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public Cache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most recent version, if available.
|
||||
*/
|
||||
public Object get(Object key, long txTimestamp) throws CacheException {
|
||||
LOG.debugf("Cache lookup: %s", key);
|
||||
|
||||
Object result = cache.get( key );
|
||||
if (result != null) LOG.debugf("Cache hit: %s", key);
|
||||
else LOG.debugf("Cache miss: %s", key);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the cache.
|
||||
*/
|
||||
public boolean put(
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version,
|
||||
Comparator versionComparator,
|
||||
boolean minimalPut) throws CacheException {
|
||||
if ( minimalPut && cache.get( key ) != null ) {
|
||||
LOG.debugf("Item already cached: %s", key);
|
||||
return false;
|
||||
}
|
||||
LOG.debugf("Caching: %s", key);
|
||||
|
||||
cache.put( key, value );
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*
|
||||
* @return null, no lock
|
||||
*/
|
||||
public SoftLock lock(Object key, Object version) throws CacheException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void remove(Object key) throws CacheException {
|
||||
LOG.debugf("Removing: %s", key);
|
||||
cache.remove( key );
|
||||
}
|
||||
|
||||
public void clear() throws CacheException {
|
||||
LOG.debugf("Clearing");
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
try {
|
||||
cache.destroy();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.unableToDestroyCache(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the item
|
||||
*/
|
||||
public void evict(Object key) throws CacheException {
|
||||
LOG.debugf("Invalidating: %s", key);
|
||||
cache.remove( key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the item
|
||||
*/
|
||||
public boolean insert(Object key, Object value, Object currentVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) {
|
||||
evict( key );
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the item (again, for safety).
|
||||
*/
|
||||
public void release(Object key, SoftLock lock) throws CacheException {
|
||||
LOG.debugf("Invalidating: %s", key);
|
||||
cache.remove( key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the item (again, for safety).
|
||||
*/
|
||||
public boolean afterUpdate(Object key, Object value, Object version, SoftLock lock) throws CacheException {
|
||||
release( key, lock );
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getRegionName() {
|
||||
return cache.getRegionName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return cache + "(nonstrict-read-write)";
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
/**
|
||||
* A contract for transactional cache implementations which support
|
||||
* optimistic locking of items within the cache.
|
||||
* <p/>
|
||||
* The optimistic locking capabilities are only utilized for
|
||||
* the entity cache regions.
|
||||
* <p/>
|
||||
* Unlike the methods on the {@link Cache} interface, all the methods
|
||||
* here will only ever be called from access scenarios where versioned
|
||||
* data is actually a possibility (i.e., entity data). Be sure to consult
|
||||
* with {@link OptimisticCacheSource#isVersioned()} to determine whether
|
||||
* versioning is actually in effect.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface OptimisticCache extends Cache {
|
||||
/**
|
||||
* Indicates the "source" of the cached data. Currently this will
|
||||
* only ever represent an {@link org.hibernate.persister.entity.EntityPersister}.
|
||||
* <p/>
|
||||
* Made available to the cache so that it can access certain information
|
||||
* about versioning strategy.
|
||||
*
|
||||
* @param source The source.
|
||||
*/
|
||||
public void setSource(OptimisticCacheSource source);
|
||||
|
||||
/**
|
||||
* Called during {@link CacheConcurrencyStrategy#insert} processing for
|
||||
* transactional strategies. Indicates we have just performed an insert
|
||||
* into the DB and now need to cache that entity's data.
|
||||
*
|
||||
* @param key The cache key.
|
||||
* @param value The data to be cached.
|
||||
* @param currentVersion The entity's version; or null if not versioned.
|
||||
*/
|
||||
public void writeInsert(Object key, Object value, Object currentVersion);
|
||||
|
||||
/**
|
||||
* Called during {@link CacheConcurrencyStrategy#update} processing for
|
||||
* transactional strategies. Indicates we have just performed an update
|
||||
* against the DB and now need to cache the updated state.
|
||||
*
|
||||
* @param key The cache key.
|
||||
* @param value The data to be cached.
|
||||
* @param currentVersion The entity's current version
|
||||
* @param previousVersion The entity's previous version (before the update);
|
||||
* or null if not versioned.
|
||||
*/
|
||||
public void writeUpdate(Object key, Object value, Object currentVersion, Object previousVersion);
|
||||
|
||||
/**
|
||||
* Called during {@link CacheConcurrencyStrategy#put} processing for
|
||||
* transactional strategies. Indicates we have just loaded an entity's
|
||||
* state from the database and need it cached.
|
||||
*
|
||||
* @param key The cache key.
|
||||
* @param value The data to be cached.
|
||||
* @param currentVersion The entity's version; or null if not versioned.
|
||||
*/
|
||||
public void writeLoad(Object key, Object value, Object currentVersion);
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* Caches data that is never updated.
|
||||
* @see org.hibernate.cache.spi.CacheConcurrencyStrategy
|
||||
*/
|
||||
@Deprecated
|
||||
public class ReadOnlyCache implements CacheConcurrencyStrategy {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, ReadOnlyCache.class.getName());
|
||||
|
||||
private Cache cache;
|
||||
|
||||
public ReadOnlyCache() {}
|
||||
|
||||
public void setCache(Cache cache) {
|
||||
this.cache=cache;
|
||||
}
|
||||
|
||||
public Cache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
public String getRegionName() {
|
||||
return cache.getRegionName();
|
||||
}
|
||||
|
||||
public synchronized Object get(Object key, long timestamp) throws CacheException {
|
||||
Object result = cache.get(key);
|
||||
if (result != null) LOG.debugf("Cache hit: %s", key);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported!
|
||||
*/
|
||||
public SoftLock lock(Object key, Object version) {
|
||||
LOG.invalidEditOfReadOnlyItem(key);
|
||||
throw new UnsupportedOperationException("Can't write to a readonly object");
|
||||
}
|
||||
|
||||
public synchronized boolean put(
|
||||
Object key,
|
||||
Object value,
|
||||
long timestamp,
|
||||
Object version,
|
||||
Comparator versionComparator,
|
||||
boolean minimalPut)
|
||||
throws CacheException {
|
||||
if ( minimalPut && cache.get(key)!=null ) {
|
||||
LOG.debugf("Item already cached: %s", key);
|
||||
return false;
|
||||
}
|
||||
LOG.debugf("Caching: %s", key);
|
||||
cache.put(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported!
|
||||
*/
|
||||
public void release(Object key, SoftLock lock) {
|
||||
LOG.invalidEditOfReadOnlyItem(key);
|
||||
//throw new UnsupportedOperationException("Can't write to a readonly object");
|
||||
}
|
||||
|
||||
public void clear() throws CacheException {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public void remove(Object key) throws CacheException {
|
||||
cache.remove(key);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
try {
|
||||
cache.destroy();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.unableToDestroyCache(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported!
|
||||
*/
|
||||
public boolean afterUpdate(Object key, Object value, Object version, SoftLock lock) throws CacheException {
|
||||
LOG.invalidEditOfReadOnlyItem(key);
|
||||
throw new UnsupportedOperationException("Can't write to a readonly object");
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
|
||||
LOG.debugf("Caching after insert: %s", key);
|
||||
cache.update(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public void evict(Object key) throws CacheException {
|
||||
// noop
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean insert(Object key, Object value, Object currentVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported!
|
||||
*/
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) {
|
||||
LOG.invalidEditOfReadOnlyItem(key);
|
||||
throw new UnsupportedOperationException("Can't write to a readonly object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return cache + "(read-only)";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,500 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* Caches data that is sometimes updated while maintaining the semantics of
|
||||
* "read committed" isolation level. If the database is set to "repeatable
|
||||
* read", this concurrency strategy <em>almost</em> maintains the semantics.
|
||||
* Repeatable read isolation is compromised in the case of concurrent writes.
|
||||
* This is an "asynchronous" concurrency strategy.<br>
|
||||
* <br>
|
||||
* If this strategy is used in a cluster, the underlying cache implementation
|
||||
* must support distributed hard locks (which are held only momentarily). This
|
||||
* strategy also assumes that the underlying cache implementation does not do
|
||||
* asynchronous replication and that state has been fully replicated as soon
|
||||
* as the lock is released.
|
||||
*
|
||||
* @see NonstrictReadWriteCache for a faster algorithm
|
||||
* @see org.hibernate.cache.spi.CacheConcurrencyStrategy
|
||||
*/
|
||||
@Deprecated
|
||||
public class ReadWriteCache implements CacheConcurrencyStrategy {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, ReadWriteCache.class.getName());
|
||||
|
||||
private Cache cache;
|
||||
private int nextLockId;
|
||||
|
||||
public ReadWriteCache() {}
|
||||
|
||||
public void setCache(Cache cache) {
|
||||
this.cache=cache;
|
||||
}
|
||||
|
||||
public Cache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
public String getRegionName() {
|
||||
return cache.getRegionName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an id for a new lock. Uniqueness per cache instance is very
|
||||
* desirable but not absolutely critical. Must be called from one of the
|
||||
* synchronized methods of this class.
|
||||
*/
|
||||
private int nextLockId() {
|
||||
if (nextLockId==Integer.MAX_VALUE) nextLockId = Integer.MIN_VALUE;
|
||||
return nextLockId++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not return an item whose timestamp is later than the current
|
||||
* transaction timestamp. (Otherwise we might compromise repeatable
|
||||
* read unnecessarily.) Do not return an item which is soft-locked.
|
||||
* Always go straight to the database instead.<br>
|
||||
* <br>
|
||||
* Note that since reading an item from that cache does not actually
|
||||
* go to the database, it is possible to see a kind of phantom read
|
||||
* due to the underlying row being updated after we have read it
|
||||
* from the cache. This would not be possible in a lock-based
|
||||
* implementation of repeatable read isolation. It is also possible
|
||||
* to overwrite changes made and committed by another transaction
|
||||
* after the current transaction read the item from the cache. This
|
||||
* problem would be caught by the update-time version-checking, if
|
||||
* the data is versioned or timestamped.
|
||||
*/
|
||||
public synchronized Object get(Object key, long txTimestamp) throws CacheException {
|
||||
LOG.debugf("Cache lookup: %s", key);
|
||||
Lockable lockable = (Lockable)cache.get(key);
|
||||
boolean gettable = lockable != null && lockable.isGettable(txTimestamp);
|
||||
if (gettable) {
|
||||
LOG.debugf("Cache hit: %s", key);
|
||||
return ((Item)lockable).getValue();
|
||||
}
|
||||
if (lockable == null) LOG.debugf("Cache miss: %s", key);
|
||||
else LOG.debugf("Cached item was locked: %s", key);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop any other transactions reading or writing this item to/from
|
||||
* the cache. Send them straight to the database instead. (The lock
|
||||
* does time out eventually.) This implementation tracks concurrent
|
||||
* locks of transactions which simultaneously attempt to write to an
|
||||
* item.
|
||||
*/
|
||||
public synchronized SoftLock lock(Object key, Object version) throws CacheException {
|
||||
LOG.debugf("Invalidating: %s", key);
|
||||
try {
|
||||
cache.lock(key);
|
||||
|
||||
Lockable lockable = (Lockable) cache.get(key);
|
||||
long timeout = cache.nextTimestamp() + cache.getTimeout();
|
||||
final Lock lock = (lockable==null) ?
|
||||
new Lock( timeout, nextLockId(), version ) :
|
||||
lockable.lock( timeout, nextLockId() );
|
||||
cache.update(key, lock);
|
||||
return lock;
|
||||
}
|
||||
finally {
|
||||
cache.unlock(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not add an item to the cache unless the current transaction
|
||||
* timestamp is later than the timestamp at which the item was
|
||||
* invalidated. (Otherwise, a stale item might be re-added if the
|
||||
* database is operating in repeatable read isolation mode.)
|
||||
* For versioned data, don't add the item unless it is the later
|
||||
* version.
|
||||
*/
|
||||
public synchronized boolean put(
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version,
|
||||
Comparator versionComparator,
|
||||
boolean minimalPut)
|
||||
throws CacheException {
|
||||
LOG.debugf("Caching: %s", key);
|
||||
|
||||
try {
|
||||
cache.lock(key);
|
||||
|
||||
Lockable lockable = (Lockable) cache.get(key);
|
||||
|
||||
boolean puttable = lockable==null ||
|
||||
lockable.isPuttable(txTimestamp, version, versionComparator);
|
||||
|
||||
if (puttable) {
|
||||
cache.put( key, new Item( value, version, cache.nextTimestamp() ) );
|
||||
LOG.debugf("Cached: %s", key);
|
||||
return true;
|
||||
}
|
||||
if (lockable.isLock()) LOG.debugf("Cached item was locked: %s", key);
|
||||
else LOG.debugf("Item already cached: %s", key);
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
cache.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* decrement a lock and put it back in the cache
|
||||
*/
|
||||
private void decrementLock(Object key, Lock lock) throws CacheException {
|
||||
//decrement the lock
|
||||
lock.unlock( cache.nextTimestamp() );
|
||||
cache.update(key, lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the soft lock on the item. Other transactions may now
|
||||
* re-cache the item (assuming that no other transaction holds a
|
||||
* simultaneous lock).
|
||||
*/
|
||||
public synchronized void release(Object key, SoftLock clientLock) throws CacheException {
|
||||
LOG.debugf("Releasing: %s", key);
|
||||
|
||||
try {
|
||||
cache.lock(key);
|
||||
|
||||
Lockable lockable = (Lockable) cache.get(key);
|
||||
if ( isUnlockable(clientLock, lockable) ) {
|
||||
decrementLock(key, (Lock) lockable);
|
||||
}
|
||||
else {
|
||||
handleLockExpiry(key);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
cache.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
void handleLockExpiry(Object key) throws CacheException {
|
||||
LOG.expired(key);
|
||||
long ts = cache.nextTimestamp() + cache.getTimeout();
|
||||
// create new lock that times out immediately
|
||||
Lock lock = new Lock( ts, nextLockId(), null );
|
||||
lock.unlock(ts);
|
||||
cache.update(key, lock);
|
||||
}
|
||||
|
||||
public void clear() throws CacheException {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public void remove(Object key) throws CacheException {
|
||||
cache.remove(key);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
try {
|
||||
cache.destroy();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.unableToDestroyCache(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-cache the updated state, if and only if there there are
|
||||
* no other concurrent soft locks. Release our lock.
|
||||
*/
|
||||
public synchronized boolean afterUpdate(Object key, Object value, Object version, SoftLock clientLock)
|
||||
throws CacheException {
|
||||
|
||||
LOG.debugf("Updating: %s", key);
|
||||
|
||||
try {
|
||||
cache.lock(key);
|
||||
|
||||
Lockable lockable = (Lockable) cache.get(key);
|
||||
if ( isUnlockable(clientLock, lockable) ) {
|
||||
Lock lock = (Lock) lockable;
|
||||
if ( lock.wasLockedConcurrently() ) {
|
||||
// just decrement the lock, don't recache
|
||||
// (we don't know which transaction won)
|
||||
decrementLock(key, lock);
|
||||
return false;
|
||||
}
|
||||
// recache the updated state
|
||||
cache.update(key, new Item(value, version, cache.nextTimestamp()));
|
||||
LOG.debugf("Updated: %s", key);
|
||||
return true;
|
||||
}
|
||||
handleLockExpiry(key);
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
cache.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the new item to the cache, checking that no other transaction has
|
||||
* accessed the item.
|
||||
*/
|
||||
public synchronized boolean afterInsert(Object key, Object value, Object version)
|
||||
throws CacheException {
|
||||
|
||||
LOG.debugf("Inserting: %s", key);
|
||||
try {
|
||||
cache.lock(key);
|
||||
|
||||
Lockable lockable = (Lockable) cache.get(key);
|
||||
if (lockable==null) {
|
||||
cache.update( key, new Item( value, version, cache.nextTimestamp() ) );
|
||||
LOG.debugf("Inserted: %s", key);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
cache.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public void evict(Object key) throws CacheException {
|
||||
// noop
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean insert(Object key, Object value, Object currentVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the client's lock commensurate with the item in the cache?
|
||||
* If it is not, we know that the cache expired the original
|
||||
* lock.
|
||||
*/
|
||||
private boolean isUnlockable(SoftLock clientLock, Lockable myLock)
|
||||
throws CacheException {
|
||||
//null clientLock is remotely possible but will never happen in practice
|
||||
return myLock!=null &&
|
||||
myLock.isLock() &&
|
||||
clientLock!=null &&
|
||||
( (Lock) clientLock ).getId()==( (Lock) myLock ).getId();
|
||||
}
|
||||
|
||||
public static interface Lockable {
|
||||
public Lock lock(long timeout, int id);
|
||||
public boolean isLock();
|
||||
public boolean isGettable(long txTimestamp);
|
||||
public boolean isPuttable(long txTimestamp, Object newVersion, Comparator comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* An item of cached data, timestamped with the time it was cached,.
|
||||
* @see ReadWriteCache
|
||||
*/
|
||||
public static final class Item implements Serializable, Lockable {
|
||||
|
||||
private final long freshTimestamp;
|
||||
private final Object value;
|
||||
private final Object version;
|
||||
|
||||
public Item(Object value, Object version, long currentTimestamp) {
|
||||
this.value = value;
|
||||
this.version = version;
|
||||
freshTimestamp = currentTimestamp;
|
||||
}
|
||||
/**
|
||||
* The timestamp on the cached data
|
||||
*/
|
||||
public long getFreshTimestamp() {
|
||||
return freshTimestamp;
|
||||
}
|
||||
/**
|
||||
* The actual cached data
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the item
|
||||
*/
|
||||
public Lock lock(long timeout, int id) {
|
||||
return new Lock(timeout, id, version);
|
||||
}
|
||||
/**
|
||||
* Not a lock!
|
||||
*/
|
||||
public boolean isLock() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Is this item visible to the timestamped
|
||||
* transaction?
|
||||
*/
|
||||
public boolean isGettable(long txTimestamp) {
|
||||
return freshTimestamp < txTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't overwite already cached items
|
||||
*/
|
||||
public boolean isPuttable(long txTimestamp, Object newVersion, Comparator comparator) {
|
||||
// we really could refresh the item if it
|
||||
// is not a lock, but it might be slower
|
||||
//return freshTimestamp < txTimestamp
|
||||
return version!=null && comparator.compare(version, newVersion) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Item{version=" + version +
|
||||
",freshTimestamp=" + freshTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A soft lock which supports concurrent locking,
|
||||
* timestamped with the time it was released
|
||||
* @author Gavin King
|
||||
*/
|
||||
public static final class Lock implements Serializable, Lockable, SoftLock {
|
||||
private long unlockTimestamp = -1;
|
||||
private int multiplicity = 1;
|
||||
private boolean concurrentLock = false;
|
||||
private long timeout;
|
||||
private final int id;
|
||||
private final Object version;
|
||||
|
||||
public Lock(long timeout, int id, Object version) {
|
||||
this.timeout = timeout;
|
||||
this.id = id;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public long getUnlockTimestamp() {
|
||||
return unlockTimestamp;
|
||||
}
|
||||
/**
|
||||
* Increment the lock, setting the
|
||||
* new lock timeout
|
||||
*/
|
||||
public Lock lock(long timeout, int id) {
|
||||
concurrentLock = true;
|
||||
multiplicity++;
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Decrement the lock, setting the unlock
|
||||
* timestamp if now unlocked
|
||||
* @param currentTimestamp
|
||||
*/
|
||||
public void unlock(long currentTimestamp) {
|
||||
if ( --multiplicity == 0 ) {
|
||||
unlockTimestamp = currentTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the timestamped transaction re-cache this
|
||||
* locked item now?
|
||||
*/
|
||||
public boolean isPuttable(long txTimestamp, Object newVersion, Comparator comparator) {
|
||||
if (timeout < txTimestamp) return true;
|
||||
if (multiplicity>0) return false;
|
||||
return version==null ?
|
||||
unlockTimestamp < txTimestamp :
|
||||
comparator.compare(version, newVersion) < 0; //by requiring <, we rely on lock timeout in the case of an unsuccessful update!
|
||||
}
|
||||
|
||||
/**
|
||||
* Was this lock held concurrently by multiple
|
||||
* transactions?
|
||||
*/
|
||||
public boolean wasLockedConcurrently() {
|
||||
return concurrentLock;
|
||||
}
|
||||
/**
|
||||
* Yes, this is a lock
|
||||
*/
|
||||
public boolean isLock() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* locks are not returned to the client!
|
||||
*/
|
||||
public boolean isGettable(long txTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getId() { return id; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Lock{id=" + id +
|
||||
",version=" + version +
|
||||
",multiplicity=" + multiplicity +
|
||||
",unlockTimestamp=" + unlockTimestamp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return cache + "(read-write)";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -38,12 +38,7 @@ import org.hibernate.service.Service;
|
|||
* <li>MyRegionFactoryImpl()</li>
|
||||
* </ul>
|
||||
* Use the first when we need to read config properties prior to
|
||||
* {@link #start(Settings, Properties)} being called. For an example, have a look at
|
||||
* {@link org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge}
|
||||
* where we need the properties in order to determine which legacy
|
||||
* {@link CacheProvider} to use so that we can answer the
|
||||
* {@link #isMinimalPutsEnabledByDefault()} question for the
|
||||
* {@link org.hibernate.cfg.SettingsFactory}.
|
||||
* {@link #start(Settings, Properties)} being called.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* Support for fully transactional cache implementations like
|
||||
* JBoss TreeCache. Note that this might be a less scalable
|
||||
* concurrency strategy than <tt>ReadWriteCache</tt>. This is
|
||||
* a "synchronous" concurrency strategy.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
@Deprecated
|
||||
public class TransactionalCache implements CacheConcurrencyStrategy {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TransactionalCache.class.getName());
|
||||
|
||||
private Cache cache;
|
||||
|
||||
public String getRegionName() {
|
||||
return cache.getRegionName();
|
||||
}
|
||||
|
||||
public Object get(Object key, long txTimestamp) throws CacheException {
|
||||
LOG.debugf("Cache lookup: %s", key);
|
||||
Object result = cache.read( key );
|
||||
if (result == null) LOG.debugf("Cache miss: %s", key);
|
||||
else LOG.debugf("Cache hit: %s", key);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean put(
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version,
|
||||
Comparator versionComparator,
|
||||
boolean minimalPut) throws CacheException {
|
||||
if ( minimalPut && cache.read( key ) != null ) {
|
||||
LOG.debugf("Item already cached: %s", key);
|
||||
return false;
|
||||
}
|
||||
LOG.debugf("Caching: %s", key);
|
||||
if ( cache instanceof OptimisticCache ) {
|
||||
( ( OptimisticCache ) cache ).writeLoad( key, value, version );
|
||||
}
|
||||
else {
|
||||
cache.put( key, value );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing, returning null.
|
||||
*/
|
||||
public SoftLock lock(Object key, Object version) throws CacheException {
|
||||
//noop
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public void release(Object key, SoftLock clientLock) throws CacheException {
|
||||
//noop
|
||||
}
|
||||
|
||||
public boolean update(
|
||||
Object key,
|
||||
Object value,
|
||||
Object currentVersion,
|
||||
Object previousVersion) throws CacheException {
|
||||
LOG.debugf("Updating: %s", key);
|
||||
if ( cache instanceof OptimisticCache ) {
|
||||
( ( OptimisticCache ) cache ).writeUpdate( key, value, currentVersion, previousVersion );
|
||||
}
|
||||
else {
|
||||
cache.update( key, value );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean insert(
|
||||
Object key,
|
||||
Object value,
|
||||
Object currentVersion) throws CacheException {
|
||||
LOG.debugf("Inserting: %s", key);
|
||||
if ( cache instanceof OptimisticCache ) {
|
||||
( ( OptimisticCache ) cache ).writeInsert( key, value, currentVersion );
|
||||
}
|
||||
else {
|
||||
cache.update( key, value );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void evict(Object key) throws CacheException {
|
||||
cache.remove( key );
|
||||
}
|
||||
|
||||
public void remove(Object key) throws CacheException {
|
||||
LOG.debugf("Removing: %s", key);
|
||||
cache.remove( key );
|
||||
}
|
||||
|
||||
public void clear() throws CacheException {
|
||||
LOG.debugf("Clearing");
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
try {
|
||||
cache.destroy();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.unableToDestroyCache(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setCache(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public Cache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean afterInsert(
|
||||
Object key,
|
||||
Object value,
|
||||
Object version) throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*/
|
||||
public boolean afterUpdate(
|
||||
Object key,
|
||||
Object value,
|
||||
Object version,
|
||||
SoftLock clientLock) throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return cache + "(transactional)";
|
||||
}
|
||||
|
||||
}
|
|
@ -104,37 +104,4 @@ public interface EntityRegionAccessStrategy extends RegionAccessStrategy{
|
|||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has become stale (before the transaction completes).
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*
|
||||
* @param key The key of the item to remove
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public void remove(Object key) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called to evict data from the entire region
|
||||
*
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public void removeAll() throws CacheException;
|
||||
|
||||
/**
|
||||
* Forcibly evict an item from the cache immediately without regard for transaction
|
||||
* isolation.
|
||||
*
|
||||
* @param key The key of the item to remove
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public void evict(Object key) throws CacheException;
|
||||
|
||||
/**
|
||||
* Forcibly evict all items from the cache immediately without regard for transaction
|
||||
* isolation.
|
||||
*
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public void evictAll() throws CacheException;
|
||||
}
|
||||
|
|
|
@ -288,13 +288,6 @@ public interface AvailableSettings {
|
|||
@Deprecated
|
||||
public static final String USER_TRANSACTION = "jta.UserTransaction";
|
||||
|
||||
/**
|
||||
* The <tt>CacheProvider</tt> implementation class
|
||||
*
|
||||
* @deprecated See {@link #CACHE_REGION_FACTORY}
|
||||
*/
|
||||
public static final String CACHE_PROVIDER = "hibernate.cache.provider_class";
|
||||
|
||||
/**
|
||||
* The {@link org.hibernate.cache.spi.RegionFactory} implementation class
|
||||
*/
|
||||
|
|
|
@ -75,11 +75,6 @@ import org.hibernate.internal.util.config.ConfigurationHelper;
|
|||
* <td>classname of <tt>org.hibernate.dialect.Dialect</tt> subclass</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><tt>hibernate.cache.provider_class</tt></td>
|
||||
* <td>classname of <tt>org.hibernate.cache.spi.CacheProvider</tt>
|
||||
* subclass (if not specified EHCache is used)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><tt>hibernate.connection.provider_class</tt></td>
|
||||
* <td>classname of <tt>org.hibernate.service.jdbc.connections.spi.ConnectionProvider</tt>
|
||||
* subclass (if not specified hueristics are used)</td>
|
||||
|
|
|
@ -55,7 +55,7 @@ public abstract class ExternalSessionFactoryConfig {
|
|||
private String querySubstitutions;
|
||||
private String showSqlEnabled;
|
||||
private String commentsEnabled;
|
||||
private String cacheProviderClass;
|
||||
private String cacheRegionFactory;
|
||||
private String cacheProviderConfig;
|
||||
private String cacheRegionPrefix;
|
||||
private String secondLevelCacheEnabled;
|
||||
|
@ -209,12 +209,12 @@ public abstract class ExternalSessionFactoryConfig {
|
|||
this.secondLevelCacheEnabled = secondLevelCacheEnabled;
|
||||
}
|
||||
|
||||
public final String getCacheProviderClass() {
|
||||
return cacheProviderClass;
|
||||
public final String getCacheRegionFactory() {
|
||||
return cacheRegionFactory;
|
||||
}
|
||||
|
||||
public final void setCacheProviderClass(String cacheProviderClass) {
|
||||
this.cacheProviderClass = cacheProviderClass;
|
||||
public final void setCacheRegionFactory(String cacheRegionFactory) {
|
||||
this.cacheRegionFactory = cacheRegionFactory;
|
||||
}
|
||||
|
||||
public String getCacheProviderConfig() {
|
||||
|
@ -287,7 +287,7 @@ public abstract class ExternalSessionFactoryConfig {
|
|||
setUnlessNull( props, Environment.QUERY_SUBSTITUTIONS, querySubstitutions );
|
||||
setUnlessNull( props, Environment.SHOW_SQL, showSqlEnabled );
|
||||
setUnlessNull( props, Environment.USE_SQL_COMMENTS, commentsEnabled );
|
||||
setUnlessNull( props, Environment.CACHE_PROVIDER, cacheProviderClass );
|
||||
setUnlessNull( props, Environment.CACHE_REGION_FACTORY, cacheRegionFactory );
|
||||
setUnlessNull( props, Environment.CACHE_PROVIDER_CONFIG, cacheProviderConfig );
|
||||
setUnlessNull( props, Environment.CACHE_REGION_PREFIX, cacheRegionPrefix );
|
||||
setUnlessNull( props, Environment.USE_MINIMAL_PUTS, minimalPutsEnabled );
|
||||
|
|
|
@ -34,9 +34,9 @@ import org.hibernate.EntityMode;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MultiTenancyStrategy;
|
||||
import org.hibernate.cache.internal.NoCachingRegionFactory;
|
||||
import org.hibernate.cache.internal.StandardQueryCacheFactory;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge;
|
||||
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.transaction.spi.TransactionFactory;
|
||||
|
@ -305,7 +305,7 @@ public class SettingsFactory implements Serializable {
|
|||
|
||||
protected QueryCacheFactory createQueryCacheFactory(Properties properties, ServiceRegistry serviceRegistry) {
|
||||
String queryCacheFactoryClassName = ConfigurationHelper.getString(
|
||||
Environment.QUERY_CACHE_FACTORY, properties, "org.hibernate.cache.internal.StandardQueryCacheFactory"
|
||||
Environment.QUERY_CACHE_FACTORY, properties, StandardQueryCacheFactory.class.getName()
|
||||
);
|
||||
LOG.debugf( "Query cache factory: %s", queryCacheFactoryClassName );
|
||||
try {
|
||||
|
@ -318,18 +318,11 @@ public class SettingsFactory implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
public static RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled, ServiceRegistry serviceRegistry) {
|
||||
private static RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled, ServiceRegistry serviceRegistry) {
|
||||
String regionFactoryClassName = ConfigurationHelper.getString(
|
||||
Environment.CACHE_REGION_FACTORY, properties, null
|
||||
);
|
||||
if ( regionFactoryClassName == null && cachingEnabled ) {
|
||||
String providerClassName = ConfigurationHelper.getString( Environment.CACHE_PROVIDER, properties, null );
|
||||
if ( providerClassName != null ) {
|
||||
// legacy behavior, apply the bridge...
|
||||
regionFactoryClassName = RegionFactoryCacheProviderBridge.class.getName();
|
||||
}
|
||||
}
|
||||
if ( regionFactoryClassName == null ) {
|
||||
if ( regionFactoryClassName == null || !cachingEnabled) {
|
||||
regionFactoryClassName = DEF_CACHE_REG_FACTORY;
|
||||
}
|
||||
LOG.debugf( "Cache region factory : %s", regionFactoryClassName );
|
||||
|
@ -355,56 +348,49 @@ public class SettingsFactory implements Serializable {
|
|||
throw new HibernateException( "could not instantiate RegionFactory [" + regionFactoryClassName + "]", e );
|
||||
}
|
||||
}
|
||||
//todo remove this once we move to new metamodel
|
||||
public static RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled) {
|
||||
// todo : REMOVE! THIS IS TOTALLY A TEMPORARY HACK FOR org.hibernate.cfg.AnnotationBinder which will be going away
|
||||
String regionFactoryClassName = ConfigurationHelper.getString(
|
||||
Environment.CACHE_REGION_FACTORY, properties, null
|
||||
);
|
||||
if ( regionFactoryClassName == null ) {
|
||||
regionFactoryClassName = DEF_CACHE_REG_FACTORY;
|
||||
}
|
||||
LOG.debugf( "Cache region factory : %s", regionFactoryClassName );
|
||||
try {
|
||||
try {
|
||||
return (RegionFactory) org.hibernate.internal.util.ReflectHelper.classForName( regionFactoryClassName )
|
||||
.getConstructor( Properties.class )
|
||||
.newInstance( properties );
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
// no constructor accepting Properties found, try no arg constructor
|
||||
LOG.debugf(
|
||||
"%s did not provide constructor accepting java.util.Properties; attempting no-arg constructor.",
|
||||
regionFactoryClassName
|
||||
);
|
||||
return (RegionFactory) org.hibernate.internal.util.ReflectHelper.classForName( regionFactoryClassName )
|
||||
.newInstance();
|
||||
}
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "could not instantiate RegionFactory [" + regionFactoryClassName + "]", e );
|
||||
}
|
||||
}
|
||||
|
||||
protected QueryTranslatorFactory createQueryTranslatorFactory(Properties properties, ServiceRegistry serviceRegistry) {
|
||||
String className = ConfigurationHelper.getString(
|
||||
Environment.QUERY_TRANSLATOR, properties, "org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory"
|
||||
);
|
||||
LOG.debugf( "Query translator: %s", className );
|
||||
LOG.debugf( "Query translator: %s", className );
|
||||
try {
|
||||
return (QueryTranslatorFactory) serviceRegistry.getService( ClassLoaderService.class )
|
||||
.classForName( className )
|
||||
.newInstance();
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "could not instantiate QueryTranslatorFactory: " + className, e );
|
||||
}
|
||||
}
|
||||
|
||||
public static RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled) {
|
||||
// todo : REMOVE! THIS IS TOTALLY A TEMPORARY HACK FOR org.hibernate.cfg.AnnotationBinder which will be going away
|
||||
String regionFactoryClassName = ConfigurationHelper.getString(
|
||||
Environment.CACHE_REGION_FACTORY, properties, null
|
||||
);
|
||||
if ( regionFactoryClassName == null && cachingEnabled ) {
|
||||
String providerClassName = ConfigurationHelper.getString( Environment.CACHE_PROVIDER, properties, null );
|
||||
if ( providerClassName != null ) {
|
||||
// legacy behavior, apply the bridge...
|
||||
regionFactoryClassName = RegionFactoryCacheProviderBridge.class.getName();
|
||||
}
|
||||
}
|
||||
if ( regionFactoryClassName == null ) {
|
||||
regionFactoryClassName = DEF_CACHE_REG_FACTORY;
|
||||
}
|
||||
LOG.debugf( "Cache region factory : %s", regionFactoryClassName );
|
||||
try {
|
||||
try {
|
||||
return (RegionFactory) org.hibernate.internal.util.ReflectHelper.classForName( regionFactoryClassName )
|
||||
.getConstructor( Properties.class )
|
||||
.newInstance( properties );
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
// no constructor accepting Properties found, try no arg constructor
|
||||
LOG.debugf(
|
||||
"%s did not provide constructor accepting java.util.Properties; attempting no-arg constructor.",
|
||||
regionFactoryClassName
|
||||
);
|
||||
return (RegionFactory) org.hibernate.internal.util.ReflectHelper.classForName( regionFactoryClassName )
|
||||
.newInstance();
|
||||
}
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "could not instantiate RegionFactory [" + regionFactoryClassName + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,11 +222,11 @@ public interface HibernateServiceMBean {
|
|||
/**
|
||||
* Get the second-level cache provider class name
|
||||
*/
|
||||
public String getCacheProviderClass();
|
||||
public String getCacheRegionFactory();
|
||||
/**
|
||||
* Set the second-level cache provider class name
|
||||
*/
|
||||
public void setCacheProviderClass(String providerClassName);
|
||||
public void setCacheRegionFactory(String cacheRegionFactory);
|
||||
/**
|
||||
* For cache providers which support this setting, get the
|
||||
* provider's specific configuration resource.
|
||||
|
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2007-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.legacy;
|
||||
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.CacheConcurrencyStrategy;
|
||||
import org.hibernate.cache.spi.CacheProvider;
|
||||
import org.hibernate.cache.internal.HashtableCacheProvider;
|
||||
import org.hibernate.cache.spi.ReadWriteCache;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class CacheTest extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testCaches() throws Exception {
|
||||
doTestCache( new HashtableCacheProvider() );
|
||||
}
|
||||
|
||||
public void doTestCache(CacheProvider cacheProvider) throws Exception {
|
||||
|
||||
Cache cache = cacheProvider.buildCache( String.class.getName(), System.getProperties() );
|
||||
|
||||
long longBefore = cache.nextTimestamp();
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
long before = cache.nextTimestamp();
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
//cache.setTimeout(1000);
|
||||
CacheConcurrencyStrategy ccs = new ReadWriteCache();
|
||||
ccs.setCache( cache );
|
||||
|
||||
// cache something
|
||||
|
||||
assertTrue( ccs.put( "foo", "foo", before, null, null, false ) );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
long after = cache.nextTimestamp();
|
||||
|
||||
assertTrue( ccs.get( "foo", longBefore ) == null );
|
||||
assertTrue( ccs.get( "foo", after ).equals( "foo" ) );
|
||||
|
||||
assertTrue( !ccs.put( "foo", "foo", before, null, null, false ) );
|
||||
|
||||
// update it:
|
||||
|
||||
SoftLock lock = ccs.lock( "foo", null );
|
||||
|
||||
assertTrue( ccs.get( "foo", after ) == null );
|
||||
assertTrue( ccs.get( "foo", longBefore ) == null );
|
||||
|
||||
assertTrue( !ccs.put( "foo", "foo", before, null, null, false ) );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
long whileLocked = cache.nextTimestamp();
|
||||
|
||||
assertTrue( !ccs.put( "foo", "foo", whileLocked, null, null, false ) );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
ccs.release( "foo", lock );
|
||||
|
||||
assertTrue( ccs.get( "foo", after ) == null );
|
||||
assertTrue( ccs.get( "foo", longBefore ) == null );
|
||||
|
||||
assertTrue( !ccs.put( "foo", "bar", whileLocked, null, null, false ) );
|
||||
assertTrue( !ccs.put( "foo", "bar", after, null, null, false ) );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
long longAfter = cache.nextTimestamp();
|
||||
|
||||
assertTrue( ccs.put( "foo", "baz", longAfter, null, null, false ) );
|
||||
|
||||
assertTrue( ccs.get( "foo", after ) == null );
|
||||
assertTrue( ccs.get( "foo", whileLocked ) == null );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
long longLongAfter = cache.nextTimestamp();
|
||||
|
||||
assertTrue( ccs.get( "foo", longLongAfter ).equals( "baz" ) );
|
||||
|
||||
// update it again, with multiple locks:
|
||||
|
||||
SoftLock lock1 = ccs.lock( "foo", null );
|
||||
SoftLock lock2 = ccs.lock( "foo", null );
|
||||
|
||||
assertTrue( ccs.get( "foo", longLongAfter ) == null );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
whileLocked = cache.nextTimestamp();
|
||||
|
||||
assertTrue( !ccs.put( "foo", "foo", whileLocked, null, null, false ) );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
ccs.release( "foo", lock2 );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
long betweenReleases = cache.nextTimestamp();
|
||||
|
||||
assertTrue( !ccs.put( "foo", "bar", betweenReleases, null, null, false ) );
|
||||
assertTrue( ccs.get( "foo", betweenReleases ) == null );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
ccs.release( "foo", lock1 );
|
||||
|
||||
assertTrue( !ccs.put( "foo", "bar", whileLocked, null, null, false ) );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
longAfter = cache.nextTimestamp();
|
||||
|
||||
assertTrue( ccs.put( "foo", "baz", longAfter, null, null, false ) );
|
||||
assertTrue( ccs.get( "foo", whileLocked ) == null );
|
||||
|
||||
Thread.sleep( 15 );
|
||||
|
||||
longLongAfter = cache.nextTimestamp();
|
||||
|
||||
assertTrue( ccs.get( "foo", longLongAfter ).equals( "baz" ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -29,7 +29,6 @@ import java.sql.SQLException;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MultiTenancyStrategy;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cache.internal.HashtableCacheProvider;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -40,6 +39,7 @@ import org.hibernate.service.jdbc.connections.spi.AbstractMultiTenantConnectionP
|
|||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.testing.cache.CachingRegionFactory;
|
||||
import org.hibernate.tool.hbm2ddl.ConnectionHelper;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
|
||||
|
@ -86,7 +86,7 @@ public class SchemaBasedMultiTenancyTest extends BaseUnitTestCase {
|
|||
|
||||
Configuration cfg = new Configuration();
|
||||
cfg.getProperties().put( Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE );
|
||||
cfg.setProperty( Environment.CACHE_PROVIDER, HashtableCacheProvider.class.getName() );
|
||||
cfg.setProperty( Environment.CACHE_REGION_FACTORY, CachingRegionFactory.class.getName() );
|
||||
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
|
||||
cfg.addAnnotatedClass( Customer.class );
|
||||
|
||||
|
|
|
@ -33,4 +33,4 @@ hibernate.show_sql true
|
|||
hibernate.max_fetch_depth 5
|
||||
|
||||
hibernate.cache.region_prefix hibernate.test
|
||||
hibernate.cache.provider_class org.hibernate.cache.internal.HashtableCacheProvider
|
||||
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
|
||||
|
|
|
@ -7,4 +7,4 @@ log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
|
|||
log4j.rootLogger=info, stdout
|
||||
|
||||
log4j.logger.org.hibernate.tool.hbm2ddl=debug
|
||||
|
||||
log4j.logger.org.hibernate.testing.cache=debug
|
||||
|
|
|
@ -1,274 +0,0 @@
|
|||
/*
|
||||
* 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.internal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Element;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.CacheException;
|
||||
|
||||
/**
|
||||
* EHCache plugin for Hibernate
|
||||
* <p/>
|
||||
* EHCache uses a {@link net.sf.ehcache.store.MemoryStore} and a
|
||||
* {@link net.sf.ehcache.store.DiskStore}.
|
||||
* The {@link net.sf.ehcache.store.DiskStore} requires that both keys and values be {@link java.io.Serializable}.
|
||||
* However the MemoryStore does not and in ehcache-1.2 nonSerializable Objects are permitted. They are discarded
|
||||
* if an attempt it made to overflow them to Disk or to replicate them to remote cache peers.
|
||||
*
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@Deprecated
|
||||
public class EhCache implements Cache {
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(EhCacheMessageLogger.class, EhCache.class.getName());
|
||||
|
||||
private static final int SIXTY_THOUSAND_MS = 60000;
|
||||
|
||||
private net.sf.ehcache.Ehcache cache;
|
||||
|
||||
/**
|
||||
* Creates a new Hibernate pluggable cache based on a cache name.
|
||||
* <p/>
|
||||
*
|
||||
* @param cache The underlying EhCache instance to use.
|
||||
*/
|
||||
public EhCache(net.sf.ehcache.Ehcache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value of an element which matches the given key.
|
||||
*
|
||||
* @param key the key of the element to return.
|
||||
* @return The value placed into the cache with an earlier put, or null if not found or expired
|
||||
* @throws org.hibernate.cache.CacheException
|
||||
*/
|
||||
public Object get(Object key) throws CacheException {
|
||||
try {
|
||||
LOG.debugf("Key: %s", key);
|
||||
if (key == null) return null;
|
||||
Element element = cache.get(key);
|
||||
if (element == null) {
|
||||
LOG.debugf("Element for %s is null", key);
|
||||
return null;
|
||||
}
|
||||
return element.getObjectValue();
|
||||
}
|
||||
catch (net.sf.ehcache.CacheException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
public Object read(Object key) throws CacheException {
|
||||
return get( key );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Puts an object into the cache.
|
||||
*
|
||||
* @param key a key
|
||||
* @param value a value
|
||||
* @throws CacheException if the {@link CacheManager}
|
||||
* is shutdown or another {@link Exception} occurs.
|
||||
*/
|
||||
public void update(Object key, Object value) throws CacheException {
|
||||
put( key, value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an object into the cache.
|
||||
*
|
||||
* @param key a key
|
||||
* @param value a value
|
||||
* @throws CacheException if the {@link CacheManager}
|
||||
* is shutdown or another {@link Exception} occurs.
|
||||
*/
|
||||
public void put(Object key, Object value) throws CacheException {
|
||||
try {
|
||||
Element element = new Element( key, value );
|
||||
cache.put( element );
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch (net.sf.ehcache.CacheException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element which matches the key.
|
||||
* <p/>
|
||||
* If no element matches, nothing is removed and no Exception is thrown.
|
||||
*
|
||||
* @param key the key of the element to remove
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void remove(Object key) throws CacheException {
|
||||
try {
|
||||
cache.remove( key );
|
||||
}
|
||||
catch (ClassCastException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch (net.sf.ehcache.CacheException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements in the cache, but leave the cache
|
||||
* in a useable state.
|
||||
*
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void clear() throws CacheException {
|
||||
try {
|
||||
cache.removeAll();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch (net.sf.ehcache.CacheException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the cache and make it unuseable.
|
||||
*
|
||||
* @throws CacheException
|
||||
*/
|
||||
public void destroy() throws CacheException {
|
||||
try {
|
||||
cache.getCacheManager().removeCache( cache.getName() );
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch (net.sf.ehcache.CacheException e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls to this method should perform there own synchronization.
|
||||
* It is provided for distributed caches. Because EHCache is not distributed
|
||||
* this method does nothing.
|
||||
*/
|
||||
public void lock(Object key) throws CacheException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls to this method should perform there own synchronization.
|
||||
* It is provided for distributed caches. Because EHCache is not distributed
|
||||
* this method does nothing.
|
||||
*/
|
||||
public void unlock(Object key) throws CacheException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next timestamp;
|
||||
*/
|
||||
public long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lock timeout for this cache.
|
||||
*/
|
||||
public int getTimeout() {
|
||||
// 60 second lock timeout
|
||||
return Timestamper.ONE_MS * SIXTY_THOUSAND_MS;
|
||||
}
|
||||
|
||||
public String getRegionName() {
|
||||
return cache.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning: This method can be very expensive to run. Allow approximately 1 second
|
||||
* per 1MB of entries. Running this method could create liveness problems
|
||||
* because the object lock is held for a long period
|
||||
* <p/>
|
||||
*
|
||||
* @return the approximate size of memory ehcache is using for the MemoryStore for this cache
|
||||
*/
|
||||
public long getSizeInMemory() {
|
||||
try {
|
||||
return cache.calculateInMemorySize();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public long getElementCountInMemory() {
|
||||
try {
|
||||
return cache.getMemoryStoreSize();
|
||||
}
|
||||
catch (net.sf.ehcache.CacheException ce) {
|
||||
throw new CacheException( ce );
|
||||
}
|
||||
}
|
||||
|
||||
public long getElementCountOnDisk() {
|
||||
return cache.getDiskStoreSize();
|
||||
}
|
||||
|
||||
public Map toMap() {
|
||||
try {
|
||||
Map result = new HashMap();
|
||||
Iterator iter = cache.getKeys().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Object key = iter.next();
|
||||
result.put( key, cache.get( key ).getObjectValue() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EHCache(" + getRegionName() + ')';
|
||||
}
|
||||
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2007-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.internal;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.CacheProvider;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.internal.util.ConfigHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Cache Provider plugin for Hibernate
|
||||
*
|
||||
* Use <code>hibernate.cache.provider_class=org.hibernate.cache.internal.EhCacheProvider</code>
|
||||
* in Hibernate 3.x or later
|
||||
*
|
||||
* Taken from EhCache 0.9 distribution
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
/**
|
||||
* Cache Provider plugin for ehcache-1.2. New in this provider are ehcache support for multiple
|
||||
* Hibernate session factories, each with its own ehcache configuration, and non Serializable keys and values.
|
||||
* Ehcache-1.2 also has many other features such as cluster support and listeners, which can be used seamlessly simply
|
||||
* by configurion in ehcache.xml.
|
||||
* <p/>
|
||||
* Use <code>hibernate.cache.provider_class=org.hibernate.cache.internal.EhCacheProvider</code> in the Hibernate configuration
|
||||
* to enable this provider for Hibernate's second level cache.
|
||||
* <p/>
|
||||
* When configuring multiple ehcache CacheManagers, as you would where you have multiple Hibernate Configurations and
|
||||
* multiple SessionFactories, specify in each Hibernate configuration the ehcache configuration using
|
||||
* the property <code>hibernate.cache.provider_configuration_file_resource_path</code> An example to set an ehcache configuration
|
||||
* called ehcache-2.xml would be <code>hibernate.cache.provider_configuration_file_resource_path=/ehcache-2.xml</code>. If the leading
|
||||
* slash is not there one will be added. The configuration file will be looked for in the root of the classpath.
|
||||
* <p/>
|
||||
* Updated for ehcache-1.2. Note this provider requires ehcache-1.2.jar. Make sure ehcache-1.1.jar or earlier
|
||||
* is not in the classpath or it will not work.
|
||||
* <p/>
|
||||
* See http://ehcache.sf.net for documentation on ehcache
|
||||
* <p/>
|
||||
*
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@Deprecated
|
||||
public class EhCacheProvider implements CacheProvider {
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(EhCacheMessageLogger.class, EhCacheProvider.class.getName());
|
||||
|
||||
private CacheManager manager;
|
||||
|
||||
/**
|
||||
* Builds a Cache.
|
||||
* <p>
|
||||
* Even though this method provides properties, they are not used.
|
||||
* Properties for EHCache are specified in the ehcache.xml file.
|
||||
* Configuration will be read from ehcache.xml for a cache declaration
|
||||
* where the name attribute matches the name parameter in this builder.
|
||||
*
|
||||
* @param name the name of the cache. Must match a cache configured in ehcache.xml
|
||||
* @param properties not used
|
||||
* @return a newly built cache will be built and initialised
|
||||
* @throws org.hibernate.cache.CacheException inter alia, if a cache of the same name already exists
|
||||
*/
|
||||
public Cache buildCache(String name, Properties properties) throws CacheException {
|
||||
try {
|
||||
net.sf.ehcache.Cache cache = manager.getCache(name);
|
||||
if (cache == null) {
|
||||
LOG.unableToFindConfiguration(name);
|
||||
manager.addCache(name);
|
||||
cache = manager.getCache(name);
|
||||
LOG.debugf("Started EHCache region: %s", name);
|
||||
}
|
||||
return new EhCache(cache);
|
||||
}
|
||||
catch (net.sf.ehcache.CacheException e) {
|
||||
throw new CacheException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next timestamp.
|
||||
*/
|
||||
public long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary initialization of the underlying cache implementation
|
||||
* during SessionFactory construction.
|
||||
*
|
||||
* @param properties current configuration settings.
|
||||
*/
|
||||
public void start(Properties properties) throws CacheException {
|
||||
if (manager != null) {
|
||||
LOG.attemptToRestartAlreadyStartedEhCacheProvider();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String configurationResourceName = null;
|
||||
if (properties != null) {
|
||||
configurationResourceName = (String) properties.get( Environment.CACHE_PROVIDER_CONFIG );
|
||||
}
|
||||
if ( StringHelper.isEmpty( configurationResourceName ) ) {
|
||||
manager = new CacheManager();
|
||||
} else {
|
||||
URL url = loadResource(configurationResourceName);
|
||||
manager = new CacheManager(url);
|
||||
}
|
||||
} catch (net.sf.ehcache.CacheException e) {
|
||||
//yukky! Don't you have subclasses for that!
|
||||
//TODO race conditions can happen here
|
||||
if (e.getMessage().startsWith("Cannot parseConfiguration CacheManager. Attempt to create a new instance of " +
|
||||
"CacheManager using the diskStorePath")) {
|
||||
throw new CacheException("Attempt to restart an already started EhCacheProvider. Use sessionFactory.close() " +
|
||||
" between repeated calls to buildSessionFactory. Consider using net.sf.ehcache.hibernate.SingletonEhCacheProvider."
|
||||
, e );
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private URL loadResource(String configurationResourceName) {
|
||||
URL url = ConfigHelper.locateConfig( configurationResourceName );
|
||||
LOG.debugf("Creating EhCacheProvider from a specified resource: %s Resolved to URL: %s", configurationResourceName, url);
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary cleanup of the underlying cache implementation
|
||||
* during SessionFactory.close().
|
||||
*/
|
||||
public void stop() {
|
||||
if (manager != null) {
|
||||
manager.shutdown();
|
||||
manager = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, 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.internal;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.util.ClassLoaderUtil;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.Logger.Level;
|
||||
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.CacheProvider;
|
||||
|
||||
/**
|
||||
* Singleton cache Provider plugin for Hibernate 3.2 and ehcache-1.2. New in this provider is support for
|
||||
* non Serializable keys and values. This provider works as a Singleton. No matter how many Hibernate Configurations
|
||||
* you have, only one ehcache CacheManager is used. See EhCacheProvider for a non-singleton implementation.
|
||||
* <p/>
|
||||
* Ehcache-1.2 also has many other features such as cluster support and listeners, which can be used seamlessly simply
|
||||
* by configurion in ehcache.xml.
|
||||
* <p/>
|
||||
* Use <code>hibernate.cache.provider_class=net.sf.ehcache.hibernate.SingletonEhCacheProvider</code> in the Hibernate configuration
|
||||
* to enable this provider for Hibernate's second level cache.
|
||||
* <p/>
|
||||
* Updated for ehcache-1.2. Note this provider requires ehcache-1.2.jar. Make sure ehcache-1.1.jar or earlier
|
||||
* is not in the classpath or it will not work.
|
||||
* <p/>
|
||||
* See http://ehcache.sf.net for documentation on ehcache
|
||||
* <p/>
|
||||
*
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
* @version $Id: SingletonEhCacheProvider.java 744 2008-08-16 20:10:49Z gregluck $
|
||||
*/
|
||||
@Deprecated
|
||||
public final class SingletonEhCacheProvider implements CacheProvider {
|
||||
|
||||
/**
|
||||
* The Hibernate system property specifying the location of the ehcache configuration file name.
|
||||
* <p/
|
||||
* If not set, ehcache.xml will be looked for in the root of the classpath.
|
||||
* <p/>
|
||||
* If set to say ehcache-1.xml, ehcache-1.xml will be looked for in the root of the classpath.
|
||||
*/
|
||||
public static final String NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME = "net.sf.ehcache.configurationResourceName";
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(EhCacheMessageLogger.class, SingletonEhCacheProvider.class.getName());
|
||||
|
||||
/**
|
||||
* To be backwardly compatible with a lot of Hibernate code out there, allow multiple starts and stops on the
|
||||
* one singleton CacheManager. Keep a count of references to only stop on when only one reference is held.
|
||||
*/
|
||||
private static int referenceCount;
|
||||
|
||||
private CacheManager manager;
|
||||
|
||||
|
||||
/**
|
||||
* Builds a Cache.
|
||||
* <p/>
|
||||
* Even though this method provides properties, they are not used.
|
||||
* Properties for EHCache are specified in the ehcache.xml file.
|
||||
* Configuration will be read from ehcache.xml for a cache declaration
|
||||
* where the name attribute matches the name parameter in this builder.
|
||||
*
|
||||
* @param name the name of the cache. Must match a cache configured in ehcache.xml
|
||||
* @param properties not used
|
||||
*
|
||||
* @return a newly built cache will be built and initialised
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException
|
||||
* inter alia, if a cache of the same name already exists
|
||||
*/
|
||||
public final Cache buildCache(String name, Properties properties) throws CacheException {
|
||||
try {
|
||||
net.sf.ehcache.Ehcache cache = manager.getEhcache( name );
|
||||
if ( cache == null ) {
|
||||
LOG.unableToFindEhCacheConfiguration(name);
|
||||
manager.addCache( name );
|
||||
cache = manager.getEhcache( name );
|
||||
LOG.debugf("Started EHCache region: %s", name);
|
||||
}
|
||||
return new EhCache( cache );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next timestamp.
|
||||
*/
|
||||
public final long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary initialization of the underlying cache implementation
|
||||
* during SessionFactory construction.
|
||||
* <p/>
|
||||
*
|
||||
* @param properties current configuration settings.
|
||||
*/
|
||||
public final void start(Properties properties) throws CacheException {
|
||||
String configurationResourceName = null;
|
||||
if ( properties != null ) {
|
||||
configurationResourceName = ( String ) properties.get( NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME );
|
||||
}
|
||||
if ( configurationResourceName == null || configurationResourceName.length() == 0 ) {
|
||||
manager = CacheManager.create();
|
||||
referenceCount++;
|
||||
}
|
||||
else {
|
||||
if ( !configurationResourceName.startsWith( "/" ) ) {
|
||||
configurationResourceName = "/" + configurationResourceName;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debugf("Prepending / to %s. It should be placed in the root of the classpath rather than in a package.",
|
||||
configurationResourceName);
|
||||
}
|
||||
}
|
||||
URL url = loadResource( configurationResourceName );
|
||||
manager = CacheManager.create( url );
|
||||
referenceCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private URL loadResource(String configurationResourceName) {
|
||||
ClassLoader standardClassloader = ClassLoaderUtil.getStandardClassLoader();
|
||||
URL url = null;
|
||||
if (standardClassloader != null) url = standardClassloader.getResource(configurationResourceName);
|
||||
if (url == null) url = this.getClass().getResource(configurationResourceName);
|
||||
if (LOG.isDebugEnabled()) LOG.debugf("Creating EhCacheProvider from a specified resource: %s Resolved to URL: %s",
|
||||
configurationResourceName,
|
||||
url);
|
||||
if (url == null && LOG.isEnabled(Level.WARN)) LOG.unableToLoadConfiguration(configurationResourceName);
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary cleanup of the underlying cache implementation
|
||||
* during SessionFactory.close().
|
||||
*/
|
||||
public void stop() {
|
||||
if ( manager != null ) {
|
||||
referenceCount--;
|
||||
if ( referenceCount == 0 ) {
|
||||
manager.shutdown();
|
||||
}
|
||||
manager = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not sure what this is supposed to do.
|
||||
*
|
||||
* @return false to be safe
|
||||
*/
|
||||
public final boolean isMinimalPutsEnabledByDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,31 +1,31 @@
|
|||
package org.hibernate.test.cache.ehcache;
|
||||
|
||||
import org.hibernate.cache.spi.ReadWriteCache.Item;
|
||||
import org.hibernate.cache.internal.EhCacheProvider;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import net.sf.ehcache.hibernate.EhCacheRegionFactory;
|
||||
|
||||
/**
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public class EhCacheRegionTest extends EhCacheTest {
|
||||
@Override
|
||||
protected void configCache(final Configuration cfg) {
|
||||
cfg.setProperty( Environment.CACHE_PROVIDER, EhCacheProvider.class.getName() );
|
||||
cfg.setProperty( Environment.CACHE_REGION_FACTORY, EhCacheRegionFactory.class.getName() );
|
||||
cfg.setProperty( Environment.CACHE_PROVIDER_CONFIG, "ehcache.xml" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map getMapFromCacheEntry(final Object entry) {
|
||||
final Map map;
|
||||
if ( entry instanceof Item ) {
|
||||
map = (Map) ( (Item) entry ).getValue();
|
||||
}
|
||||
else {
|
||||
// if ( entry instanceof Item ) {
|
||||
// map = (Map) ( (Item) entry ).getValue();
|
||||
// }
|
||||
// else {
|
||||
map = (Map) entry;
|
||||
}
|
||||
// }
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@ package org.hibernate.test.cache.ehcache;
|
|||
import java.util.Map;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.cache.internal.EhCacheProvider;
|
||||
import org.hibernate.cache.spi.ReadWriteCache;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
|
||||
|
@ -184,10 +182,11 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
|
|||
|
||||
Object entry = slcs.getEntries().get( item.getId() );
|
||||
Long cachedVersionValue;
|
||||
if ( entry instanceof ReadWriteCache.Lock ) {
|
||||
//FIXME don't know what to test here
|
||||
cachedVersionValue = Long.valueOf( ((ReadWriteCache.Lock) entry).getUnlockTimestamp() );
|
||||
} else if(entry.getClass().getName().equals("net.sf.ehcache.hibernate.strategy.AbstractReadWriteEhcacheAccessStrategy$Lock")) {
|
||||
// if ( entry instanceof ReadWriteCache.Lock ) {
|
||||
// //FIXME don't know what to test here
|
||||
// cachedVersionValue = Long.valueOf( ((ReadWriteCache.Lock) entry).getUnlockTimestamp() );
|
||||
// } else
|
||||
if(entry.getClass().getName().equals("net.sf.ehcache.hibernate.strategy.AbstractReadWriteEhcacheAccessStrategy$Lock")) {
|
||||
//FIXME don't know what to test here
|
||||
} else {
|
||||
cachedVersionValue = ( Long ) getMapFromCacheEntry(entry).get( "_version" );
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<property name="hibernate.max_fetch_depth">3</property>
|
||||
<property name="hibernate.hbm2ddl.auto">create-drop</property>
|
||||
<property name="hibernate.generate_statistics">true</property>
|
||||
<property name="hibernate.cache.provider_class">org.hibernate.cache.internal.HashtableCacheProvider</property>
|
||||
<property name="hibernate.cache.region.factory_class">org.hibernate.testing.cache.CachingRegionFactory</property>
|
||||
<mapping class="org.hibernate.ejb.test.Item"/>
|
||||
<mapping class="org.hibernate.ejb.test.Cat"/>
|
||||
<mapping class="org.hibernate.ejb.test.Kitten"/>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<property name="hibernate.connection.password" value="@jdbc.pass@"/>
|
||||
<property name="hibernate.connection.url" value="@jdbc.url@"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<property name="hibernate.connection.password" value="@jdbc.pass@"/>
|
||||
<property name="hibernate.connection.url" value="@jdbc.url@"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<property name="hibernate.connection.password" value="@jdbc.pass@"/>
|
||||
<property name="hibernate.connection.url" value="@jdbc.url@"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
<property name="hibernate.archive.autodetection" value="class"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<property name="hibernate.max_fetch_depth" value="3"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.generate_statistics" value="true"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.ejb.test.MyNamingStrategy"/>
|
||||
<!-- test naming strategy and fall back to element content -->
|
||||
<!-- property name="hibernate.ejb.naming_strategy">org.hibernate.ejb.test.MyNamingStrategy</property -->
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<property name="hibernate.connection.password" value="@jdbc.pass@"/>
|
||||
<property name="hibernate.connection.url" value="@jdbc.url@"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<properties>
|
||||
<property name="hibernate.dialect" value="@db.dialect@"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<property name="hibernate.connection.password" value="@jdbc.pass@"/>
|
||||
<property name="hibernate.connection.url" value="@jdbc.url@"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<property name="hibernate.connection.password" value="@jdbc.pass@"/>
|
||||
<property name="hibernate.connection.url" value="@jdbc.url@"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.HashtableCacheProvider"/>
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.testing.cache.CachingRegionFactory" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
|
@ -33,6 +33,6 @@ hibernate.show_sql true
|
|||
hibernate.max_fetch_depth 5
|
||||
|
||||
hibernate.cache.region_prefix hibernate.test
|
||||
hibernate.cache.provider_class org.hibernate.cache.internal.HashtableCacheProvider
|
||||
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
|
||||
|
||||
hibernate.jdbc.batch_size 0
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<property name="hibernate.max_fetch_depth">3</property>
|
||||
<property name="hibernate.hbm2ddl.auto">create-drop</property>
|
||||
<property name="hibernate.generate_statistics">true</property>
|
||||
<property name="hibernate.cache.provider_class">org.hibernate.cache.internal.HashtableCacheProvider</property>
|
||||
<property name="hibernate.cache.region.factory_class">org.hibernate.testing.cache.CachingRegionFactory</property>
|
||||
<mapping class="org.hibernate.ejb.test.Item"/>
|
||||
<mapping class="org.hibernate.ejb.test.Cat"/>
|
||||
<mapping class="org.hibernate.ejb.test.Kitten"/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.hibernate.envers.test.integration.cache;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cache.internal.EhCacheProvider;
|
||||
import org.hibernate.cache.internal.EhCacheRegionFactory;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.envers.RevisionType;
|
||||
|
@ -26,7 +26,7 @@ public class HibernateSecLvlQueryCache extends AbstractSessionTest {
|
|||
config.addAnnotatedClass(StrTestEntity.class);
|
||||
config.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true");
|
||||
config.setProperty(Environment.USE_QUERY_CACHE, "true");
|
||||
config.setProperty(Environment.CACHE_PROVIDER, EhCacheProvider.class.getName());
|
||||
config.setProperty(Environment.CACHE_REGION_FACTORY, EhCacheRegionFactory.class.getName());
|
||||
config.setProperty(Environment.CACHE_PROVIDER_CONFIG, "ehcache-test.xml");
|
||||
}
|
||||
|
||||
|
|
360
hibernate-testing/src/main/java/org/hibernate/testing/cache/AbstractReadWriteAccessStrategy.java
vendored
Normal file
360
hibernate-testing/src/main/java/org/hibernate/testing/cache/AbstractReadWriteAccessStrategy.java
vendored
Normal file
|
@ -0,0 +1,360 @@
|
|||
package org.hibernate.testing.cache;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
abstract class AbstractReadWriteAccessStrategy extends BaseRegionAccessStrategy {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, AbstractReadWriteAccessStrategy.class.getName()
|
||||
);
|
||||
private final UUID uuid = UUID.randomUUID();
|
||||
private final AtomicLong nextLockId = new AtomicLong();
|
||||
private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
|
||||
protected java.util.concurrent.locks.Lock readLock = reentrantReadWriteLock.readLock();
|
||||
protected java.util.concurrent.locks.Lock writeLock = reentrantReadWriteLock.writeLock();
|
||||
|
||||
/**
|
||||
* Returns <code>null</code> if the item is not readable. Locked items are not readable, nor are items created
|
||||
* after the start of this transaction.
|
||||
*/
|
||||
@Override
|
||||
public final Object get(Object key, long txTimestamp) throws CacheException {
|
||||
try {
|
||||
readLock.lock();
|
||||
Lockable item = (Lockable) getInternalRegion().get( key );
|
||||
|
||||
boolean readable = item != null && item.isReadable( txTimestamp );
|
||||
if ( readable ) {
|
||||
return item.getValue();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
abstract Comparator getVersionComparator();
|
||||
|
||||
/**
|
||||
* Returns <code>false</code> and fails to put the value if there is an existing un-writeable item mapped to this
|
||||
* key.
|
||||
*/
|
||||
@Override
|
||||
public final boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
||||
throws CacheException {
|
||||
try {
|
||||
writeLock.lock();
|
||||
Lockable item = (Lockable) getInternalRegion().get( key );
|
||||
boolean writeable = item == null || item.isWriteable( txTimestamp, version, getVersionComparator() );
|
||||
if ( writeable ) {
|
||||
getInternalRegion().put( key, new Item( value, version, getInternalRegion().nextTimestamp() ) );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-lock a cache item.
|
||||
*/
|
||||
public final SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
|
||||
try {
|
||||
writeLock.lock();
|
||||
Lockable item = (Lockable) getInternalRegion().get( key );
|
||||
long timeout = getInternalRegion().nextTimestamp() + getInternalRegion().getTimeout();
|
||||
final Lock lock = ( item == null ) ? new Lock( timeout, uuid, nextLockId(), version ) : item.lock(
|
||||
timeout,
|
||||
uuid,
|
||||
nextLockId()
|
||||
);
|
||||
getInternalRegion().put( key, lock );
|
||||
return lock;
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-unlock a cache item.
|
||||
*/
|
||||
public final void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
|
||||
try {
|
||||
writeLock.lock();
|
||||
Lockable item = (Lockable) getInternalRegion().get( key );
|
||||
|
||||
if ( ( item != null ) && item.isUnlockable( lock ) ) {
|
||||
decrementLock( key, (Lock) item );
|
||||
}
|
||||
else {
|
||||
handleLockExpiry( key, item );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private long nextLockId() {
|
||||
return nextLockId.getAndIncrement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock and re-put the given key, lock combination.
|
||||
*/
|
||||
protected void decrementLock(Object key, Lock lock) {
|
||||
lock.unlock( getInternalRegion().nextTimestamp() );
|
||||
getInternalRegion().put( key, lock );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the timeout of a previous lock mapped to this key
|
||||
*/
|
||||
protected void handleLockExpiry(Object key, Lockable lock) {
|
||||
LOG.expired(key);
|
||||
long ts = getInternalRegion().nextTimestamp() + getInternalRegion().getTimeout();
|
||||
// create new lock that times out immediately
|
||||
Lock newLock = new Lock( ts, uuid, nextLockId.getAndIncrement(), null );
|
||||
newLock.unlock( ts );
|
||||
getInternalRegion().put( key, newLock );
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface type implemented by all wrapper objects in the cache.
|
||||
*/
|
||||
protected static interface Lockable {
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the enclosed value can be read by a transaction started at the given time.
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp);
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the enclosed value can be replaced with one of the given version by a
|
||||
* transaction started at the given time.
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object version, Comparator versionComparator);
|
||||
|
||||
/**
|
||||
* Returns the enclosed value.
|
||||
*/
|
||||
public Object getValue();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the given lock can be unlocked using the given SoftLock instance as a handle.
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock);
|
||||
|
||||
/**
|
||||
* Locks this entry, stamping it with the UUID and lockId given, with the lock timeout occuring at the specified
|
||||
* time. The returned Lock object can be used to unlock the entry in the future.
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper type representing unlocked items.
|
||||
*/
|
||||
protected final static class Item implements Serializable, Lockable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Object value;
|
||||
private final Object version;
|
||||
private final long timestamp;
|
||||
|
||||
/**
|
||||
* Creates an unlocked item wrapping the given value with a version and creation timestamp.
|
||||
*/
|
||||
Item(Object value, Object version, long timestamp) {
|
||||
this.value = value;
|
||||
this.version = version;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp) {
|
||||
return txTimestamp > timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||
return version != null && versionComparator.compare( version, newVersion ) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||
return new Lock( timeout, uuid, lockId, version );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper type representing locked items.
|
||||
*/
|
||||
protected final static class Lock implements Serializable, Lockable, SoftLock {
|
||||
|
||||
private static final long serialVersionUID = 2L;
|
||||
|
||||
private final UUID sourceUuid;
|
||||
private final long lockId;
|
||||
private final Object version;
|
||||
|
||||
private long timeout;
|
||||
private boolean concurrent;
|
||||
private int multiplicity = 1;
|
||||
private long unlockTimestamp;
|
||||
|
||||
/**
|
||||
* Creates a locked item with the given identifiers and object version.
|
||||
*/
|
||||
Lock(long timeout, UUID sourceUuid, long lockId, Object version) {
|
||||
this.timeout = timeout;
|
||||
this.lockId = lockId;
|
||||
this.version = version;
|
||||
this.sourceUuid = sourceUuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||
if ( txTimestamp > timeout ) {
|
||||
// if timedout then allow write
|
||||
return true;
|
||||
}
|
||||
if ( multiplicity > 0 ) {
|
||||
// if still locked then disallow write
|
||||
return false;
|
||||
}
|
||||
return version == null ? txTimestamp > unlockTimestamp : versionComparator.compare(
|
||||
version,
|
||||
newVersion
|
||||
) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock) {
|
||||
return equals( lock );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( o == this ) {
|
||||
return true;
|
||||
}
|
||||
else if ( o instanceof Lock ) {
|
||||
return ( lockId == ( (Lock) o ).lockId ) && sourceUuid.equals( ( (Lock) o ).sourceUuid );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = ( sourceUuid != null ? sourceUuid.hashCode() : 0 );
|
||||
int temp = (int) lockId;
|
||||
for ( int i = 1; i < Long.SIZE / Integer.SIZE; i++ ) {
|
||||
temp ^= ( lockId >>> ( i * Integer.SIZE ) );
|
||||
}
|
||||
return hash + temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this Lock has been concurrently locked by more than one transaction.
|
||||
*/
|
||||
public boolean wasLockedConcurrently() {
|
||||
return concurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||
concurrent = true;
|
||||
multiplicity++;
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks this Lock, and timestamps the unlock event.
|
||||
*/
|
||||
public void unlock(long timestamp) {
|
||||
if ( --multiplicity == 0 ) {
|
||||
unlockTimestamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder( "Lock Source-UUID:" + sourceUuid + " Lock-ID:" + lockId );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
|
@ -21,37 +21,34 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.internal.bridge;
|
||||
package org.hibernate.testing.cache;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public abstract class BaseGeneralDataRegionAdapter extends BaseRegionAdapter implements GeneralDataRegion {
|
||||
class BaseCollectionRegionAccessStrategy extends BaseRegionAccessStrategy implements CollectionRegionAccessStrategy {
|
||||
private final CollectionRegionImpl region;
|
||||
|
||||
protected BaseGeneralDataRegionAdapter(Cache underlyingCache, Settings settings) {
|
||||
super( underlyingCache, settings );
|
||||
@Override
|
||||
protected BaseGeneralDataRegion getInternalRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public Object get(Object key) throws CacheException {
|
||||
return underlyingCache.get( key );
|
||||
@Override
|
||||
protected boolean isDefaultMinimalPutOverride() {
|
||||
return region.getSettings().isMinimalPutsEnabled();
|
||||
}
|
||||
|
||||
public void put(Object key, Object value) throws CacheException {
|
||||
underlyingCache.put( key, value );
|
||||
@Override
|
||||
public CollectionRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public void evict(Object key) throws CacheException {
|
||||
underlyingCache.remove( key );
|
||||
}
|
||||
|
||||
public void evictAll() throws CacheException {
|
||||
underlyingCache.clear();
|
||||
BaseCollectionRegionAccessStrategy(CollectionRegionImpl region) {
|
||||
this.region = region;
|
||||
}
|
||||
}
|
85
hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseEntityRegionAccessStrategy.java
vendored
Normal file
85
hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseEntityRegionAccessStrategy.java
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class BaseEntityRegionAccessStrategy extends BaseRegionAccessStrategy implements EntityRegionAccessStrategy {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, BaseEntityRegionAccessStrategy.class.getName()
|
||||
);
|
||||
private final EntityRegionImpl region;
|
||||
|
||||
BaseEntityRegionAccessStrategy(EntityRegionImpl region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EntityRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insert(Object key, Object value, Object version) throws CacheException {
|
||||
return putFromLoad( key, value, 0, version );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
|
||||
throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||
throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseGeneralDataRegion getInternalRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDefaultMinimalPutOverride() {
|
||||
return region.getSettings().isMinimalPutsEnabled();
|
||||
}
|
||||
}
|
91
hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseGeneralDataRegion.java
vendored
Normal file
91
hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseGeneralDataRegion.java
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class BaseGeneralDataRegion extends BaseRegion implements GeneralDataRegion {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, BaseGeneralDataRegion.class.getName()
|
||||
);
|
||||
|
||||
BaseGeneralDataRegion(String name) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object key) throws CacheException {
|
||||
LOG.debugf( "Cache lookup : key[%s]", key );
|
||||
if ( key == null ) {
|
||||
return null;
|
||||
}
|
||||
Object result = cache.get( key );
|
||||
if ( result != null ) {
|
||||
LOG.debugf( "Cache hit: %s", key );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Object key, Object value) throws CacheException {
|
||||
LOG.debugf( "Caching : [%s] -> [%s]", key, value );
|
||||
if ( key == null || value == null ) {
|
||||
LOG.debug( "Key or Value is null" );
|
||||
return;
|
||||
}
|
||||
cache.put( key, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Object key) throws CacheException {
|
||||
LOG.debugf( "Invalidating: %s", key );
|
||||
if ( key == null ) {
|
||||
LOG.debug( "Key is null" );
|
||||
return;
|
||||
}
|
||||
cache.remove( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictAll() throws CacheException {
|
||||
LOG.debug( "evict cache" );
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
|
@ -21,67 +21,72 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.internal.bridge;
|
||||
package org.hibernate.testing.cache;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.internal.Timestamper;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Basic adapter bridging between {@link Region} and {@link Cache}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public abstract class BaseRegionAdapter implements Region {
|
||||
protected final Cache underlyingCache;
|
||||
protected final Settings settings;
|
||||
class BaseRegion implements Region {
|
||||
protected final Map cache = new ConcurrentHashMap();
|
||||
private final String name;
|
||||
|
||||
protected BaseRegionAdapter(Cache underlyingCache, Settings settings) {
|
||||
this.underlyingCache = underlyingCache;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return underlyingCache.getRegionName();
|
||||
}
|
||||
|
||||
public void clear() throws CacheException {
|
||||
underlyingCache.clear();
|
||||
}
|
||||
|
||||
public void destroy() throws CacheException {
|
||||
underlyingCache.destroy();
|
||||
BaseRegion(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object key) {
|
||||
// safer to utilize the toMap() as oposed to say get(key) != null
|
||||
return underlyingCache.toMap().containsKey( key );
|
||||
return key != null ? cache.containsKey( key ) : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws CacheException {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeInMemory() {
|
||||
return underlyingCache.getSizeInMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getElementCountInMemory() {
|
||||
return underlyingCache.getElementCountInMemory();
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getElementCountOnDisk() {
|
||||
return underlyingCache.getElementCountOnDisk();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map toMap() {
|
||||
return underlyingCache.toMap();
|
||||
return Collections.unmodifiableMap( cache );
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextTimestamp() {
|
||||
return underlyingCache.nextTimestamp();
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
return underlyingCache.getTimeout();
|
||||
return Timestamper.ONE_MS * 60000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
109
hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseRegionAccessStrategy.java
vendored
Normal file
109
hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseRegionAccessStrategy.java
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||
import org.hibernate.cache.spi.access.RegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
abstract class BaseRegionAccessStrategy implements RegionAccessStrategy {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, BaseRegionAccessStrategy.class.getName()
|
||||
);
|
||||
|
||||
protected abstract BaseGeneralDataRegion getInternalRegion();
|
||||
protected abstract boolean isDefaultMinimalPutOverride();
|
||||
@Override
|
||||
public Object get(Object key, long txTimestamp) throws CacheException {
|
||||
return getInternalRegion().get( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
|
||||
return putFromLoad( key, value, txTimestamp, version, isDefaultMinimalPutOverride() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
||||
throws CacheException {
|
||||
|
||||
if ( key == null || value == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( minimalPutOverride && getInternalRegion().contains( key ) ) {
|
||||
LOG.debugf( "Item already cached: %s", key );
|
||||
return false;
|
||||
}
|
||||
LOG.debugf( "Caching: %s", key );
|
||||
getInternalRegion().put( key, value );
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftLock lockRegion() throws CacheException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||
evictAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Object key) throws CacheException {
|
||||
evict( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() throws CacheException {
|
||||
evictAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Object key) throws CacheException {
|
||||
getInternalRegion().evict( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictAll() throws CacheException {
|
||||
getInternalRegion().evictAll();
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
|
@ -21,35 +21,30 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.internal.bridge;
|
||||
package org.hibernate.testing.cache;
|
||||
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.TransactionAwareCache;
|
||||
import org.hibernate.cache.spi.TransactionalDataRegion;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public abstract class BaseTransactionalDataRegionAdapter
|
||||
extends BaseRegionAdapter
|
||||
implements TransactionalDataRegion {
|
||||
class BaseTransactionalDataRegion extends BaseGeneralDataRegion implements TransactionalDataRegion {
|
||||
private final CacheDataDescription metadata;
|
||||
|
||||
protected final CacheDataDescription metadata;
|
||||
|
||||
protected BaseTransactionalDataRegionAdapter(Cache underlyingCache, Settings settings, CacheDataDescription metadata) {
|
||||
super( underlyingCache, settings );
|
||||
BaseTransactionalDataRegion(String name, CacheDataDescription metadata) {
|
||||
super( name );
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public boolean isTransactionAware() {
|
||||
return underlyingCache instanceof TransactionAwareCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheDataDescription getCacheDataDescription() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAware() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
116
hibernate-testing/src/main/java/org/hibernate/testing/cache/CachingRegionFactory.java
vendored
Normal file
116
hibernate-testing/src/main/java/org/hibernate/testing/cache/CachingRegionFactory.java
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.internal.Timestamper;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public class CachingRegionFactory implements RegionFactory {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, CachingRegionFactory.class.getName()
|
||||
);
|
||||
private Settings settings;
|
||||
public CachingRegionFactory() {
|
||||
LOG.warn( "CachingRegionFactory should be only used for testing." );
|
||||
}
|
||||
|
||||
public CachingRegionFactory(Properties properties) {
|
||||
//add here to avoid run into catch
|
||||
LOG.warn( "CachingRegionFactory should be only used for testing." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
this.settings=settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessType getDefaultAccessType() {
|
||||
return AccessType.NONSTRICT_READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
return new EntityRegionImpl( regionName, metadata, settings );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
return new CollectionRegionImpl( regionName, metadata, settings );
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new QueryResultsRegionImpl( regionName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new TimestampsRegionImpl( regionName );
|
||||
}
|
||||
|
||||
private static class QueryResultsRegionImpl extends BaseGeneralDataRegion implements QueryResultsRegion {
|
||||
QueryResultsRegionImpl(String name) {
|
||||
super( name );
|
||||
}
|
||||
}
|
||||
|
||||
private static class TimestampsRegionImpl extends BaseGeneralDataRegion implements TimestampsRegion {
|
||||
TimestampsRegionImpl(String name) {
|
||||
super( name );
|
||||
}
|
||||
}
|
||||
}
|
74
hibernate-testing/src/main/java/org/hibernate/testing/cache/CollectionRegionImpl.java
vendored
Normal file
74
hibernate-testing/src/main/java/org/hibernate/testing/cache/CollectionRegionImpl.java
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class CollectionRegionImpl extends BaseTransactionalDataRegion implements CollectionRegion {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, CollectionRegionImpl.class.getName()
|
||||
);
|
||||
private final Settings settings;
|
||||
CollectionRegionImpl(String name, CacheDataDescription metadata, Settings settings) {
|
||||
super( name, metadata );
|
||||
this.settings=settings;
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
switch ( accessType ) {
|
||||
case READ_ONLY:
|
||||
if ( getCacheDataDescription().isMutable() ) {
|
||||
LOG.warnf( "read-only cache configured for mutable collection [ %s ]", getName() );
|
||||
}
|
||||
return new ReadOnlyCollectionRegionAccessStrategy( this );
|
||||
case READ_WRITE:
|
||||
return new ReadWriteCollectionRegionAccessStrategy( this );
|
||||
case NONSTRICT_READ_WRITE:
|
||||
return new NonstrictReadWriteCollectionRegionAccessStrategy( this );
|
||||
case TRANSACTIONAL:
|
||||
|
||||
throw new UnsupportedOperationException( "doesn't support this access strategy" );
|
||||
default:
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
78
hibernate-testing/src/main/java/org/hibernate/testing/cache/EntityRegionImpl.java
vendored
Normal file
78
hibernate-testing/src/main/java/org/hibernate/testing/cache/EntityRegionImpl.java
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class EntityRegionImpl extends BaseTransactionalDataRegion implements EntityRegion {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, EntityRegionImpl.class.getName()
|
||||
);
|
||||
private final Settings settings;
|
||||
|
||||
|
||||
EntityRegionImpl(String name, CacheDataDescription metadata, Settings settings) {
|
||||
super( name, metadata );
|
||||
this.settings = settings;
|
||||
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
switch ( accessType ) {
|
||||
case READ_ONLY:
|
||||
if ( getCacheDataDescription().isMutable() ) {
|
||||
LOG.warnf( "read-only cache configured for mutable entity [ %s ]", getName() );
|
||||
}
|
||||
return new ReadOnlyEntityRegionAccessStrategy( this );
|
||||
case READ_WRITE:
|
||||
return new ReadWriteEntityRegionAccessStrategy( this );
|
||||
case NONSTRICT_READ_WRITE:
|
||||
return new NonstrictReadWriteEntityRegionAccessStrategy( this );
|
||||
case TRANSACTIONAL:
|
||||
// throw new UnsupportedOperationException( "doesn't support this access strategy" );
|
||||
return new NonstrictReadWriteEntityRegionAccessStrategy( this );
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2011, Red Hat Inc. 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 Inc.
|
||||
|
@ -21,30 +21,28 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.internal.bridge;
|
||||
package org.hibernate.testing.cache;
|
||||
|
||||
import java.util.Comparator;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.OptimisticCacheSource;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class OptimisticCacheSourceAdapter implements OptimisticCacheSource {
|
||||
private final CacheDataDescription dataDescription;
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class NonstrictReadWriteCollectionRegionAccessStrategy extends BaseCollectionRegionAccessStrategy {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, NonstrictReadWriteCollectionRegionAccessStrategy.class.getName()
|
||||
);
|
||||
|
||||
public OptimisticCacheSourceAdapter(CacheDataDescription dataDescription) {
|
||||
this.dataDescription = dataDescription;
|
||||
NonstrictReadWriteCollectionRegionAccessStrategy(CollectionRegionImpl region) {
|
||||
super( region );
|
||||
}
|
||||
@Override
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
evict( key );
|
||||
}
|
||||
|
||||
public boolean isVersioned() {
|
||||
return dataDescription.isVersioned();
|
||||
}
|
||||
|
||||
public Comparator getVersionComparator() {
|
||||
return dataDescription.getVersionComparator();
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2011, Red Hat Inc. 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 Inc.
|
||||
|
@ -21,48 +21,41 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
package org.hibernate.testing.cache;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.CacheProvider;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* A simple in-memory Hashtable-based cache impl.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public class HashtableCacheProvider implements CacheProvider {
|
||||
|
||||
public Cache buildCache(String regionName, Properties properties) throws CacheException {
|
||||
return new HashtableCache( regionName );
|
||||
class NonstrictReadWriteEntityRegionAccessStrategy extends BaseEntityRegionAccessStrategy {
|
||||
NonstrictReadWriteEntityRegionAccessStrategy(EntityRegionImpl region) {
|
||||
super( region );
|
||||
}
|
||||
|
||||
public long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
@Override
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
evict( key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary initialization of the underlying cache implementation
|
||||
* during SessionFactory construction.
|
||||
*
|
||||
* @param properties current configuration settings.
|
||||
*/
|
||||
public void start(Properties properties) throws CacheException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to perform any necessary cleanup of the underlying cache implementation
|
||||
* during SessionFactory.close().
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
@Override
|
||||
public boolean insert(Object key, Object value, Object version) throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
|
||||
throws CacheException {
|
||||
evict( key );
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class ReadOnlyCollectionRegionAccessStrategy extends BaseCollectionRegionAccessStrategy {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, ReadOnlyCollectionRegionAccessStrategy.class.getName()
|
||||
);
|
||||
|
||||
ReadOnlyCollectionRegionAccessStrategy(CollectionRegionImpl region) {
|
||||
super( region );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
LOG.invalidEditOfReadOnlyItem( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
LOG.invalidEditOfReadOnlyItem( key );
|
||||
throw new UnsupportedOperationException( "Can't write to a readonly object" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Object key) throws CacheException {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class ReadOnlyEntityRegionAccessStrategy extends BaseEntityRegionAccessStrategy {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class, ReadOnlyEntityRegionAccessStrategy.class.getName()
|
||||
);
|
||||
|
||||
ReadOnlyEntityRegionAccessStrategy(EntityRegionImpl region) {
|
||||
super( region );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Object key) throws CacheException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insert(Object key, Object value, Object version) throws CacheException {
|
||||
return false; //wait until tx complete, see afterInsert().
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
|
||||
getInternalRegion().put( key, value ); //save into cache since the tx is completed
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
LOG.invalidEditOfReadOnlyItem( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
LOG.invalidEditOfReadOnlyItem( key );
|
||||
throw new UnsupportedOperationException( "Can't write to a readonly object" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
|
||||
throws CacheException {
|
||||
LOG.invalidEditOfReadOnlyItem( key );
|
||||
throw new UnsupportedOperationException( "Can't write to a readonly object" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||
throws CacheException {
|
||||
LOG.invalidEditOfReadOnlyItem( key );
|
||||
throw new UnsupportedOperationException( "Can't write to a readonly object" );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
|
@ -21,19 +21,44 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.internal.bridge;
|
||||
package org.hibernate.testing.cache;
|
||||
|
||||
import org.hibernate.cache.spi.Cache;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Adapter specifically briding {@link org.hibernate.cache.spi.QueryResultsRegion} to {@link Cache}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public class QueryResultsRegionAdapter extends BaseGeneralDataRegionAdapter implements QueryResultsRegion {
|
||||
protected QueryResultsRegionAdapter(Cache underlyingCache, Settings settings) {
|
||||
super( underlyingCache, settings );
|
||||
class ReadWriteCollectionRegionAccessStrategy extends AbstractReadWriteAccessStrategy
|
||||
implements CollectionRegionAccessStrategy {
|
||||
|
||||
private final CollectionRegionImpl region;
|
||||
|
||||
ReadWriteCollectionRegionAccessStrategy(CollectionRegionImpl region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
@Override
|
||||
Comparator getVersionComparator() {
|
||||
return region.getCacheDataDescription().getVersionComparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseGeneralDataRegion getInternalRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDefaultMinimalPutOverride() {
|
||||
return region.getSettings().isMinimalPutsEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
|
||||
}
|
127
hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteEntityRegionAccessStrategy.java
vendored
Normal file
127
hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteEntityRegionAccessStrategy.java
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010-2011, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.testing.cache;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
class ReadWriteEntityRegionAccessStrategy extends AbstractReadWriteAccessStrategy
|
||||
implements EntityRegionAccessStrategy {
|
||||
private final EntityRegionImpl region;
|
||||
|
||||
ReadWriteEntityRegionAccessStrategy(EntityRegionImpl region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insert(Object key, Object value, Object version) throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
|
||||
throws CacheException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Object key) throws CacheException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
|
||||
|
||||
try {
|
||||
writeLock.lock();
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
if ( item == null ) {
|
||||
region.put( key, new Item( value, version, region.nextTimestamp() ) );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||
throws CacheException {
|
||||
try {
|
||||
writeLock.lock();
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
|
||||
if ( item != null && item.isUnlockable( lock ) ) {
|
||||
Lock lockItem = (Lock) item;
|
||||
if ( lockItem.wasLockedConcurrently() ) {
|
||||
decrementLock( key, lockItem );
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
region.put( key, new Item( value, currentVersion, region.nextTimestamp() ) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
handleLockExpiry( key, item );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected BaseGeneralDataRegion getInternalRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDefaultMinimalPutOverride() {
|
||||
return region.getSettings().isMinimalPutsEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
Comparator getVersionComparator() {
|
||||
return region.getCacheDataDescription().getVersionComparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
}
|
|
@ -37,7 +37,6 @@ import java.util.Properties;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cache.internal.HashtableCacheProvider;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
@ -62,6 +61,7 @@ import org.hibernate.testing.BeforeClassOnce;
|
|||
import org.hibernate.testing.OnExpectedFailure;
|
||||
import org.hibernate.testing.OnFailure;
|
||||
import org.hibernate.testing.SkipLog;
|
||||
import org.hibernate.testing.cache.CachingRegionFactory;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
|
@ -130,7 +130,7 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase {
|
|||
|
||||
protected Configuration constructConfiguration() {
|
||||
Configuration configuration = new Configuration()
|
||||
.setProperty( Environment.CACHE_PROVIDER, HashtableCacheProvider.class.getName() );
|
||||
.setProperty(Environment.CACHE_REGION_FACTORY, CachingRegionFactory.class.getName() );
|
||||
configuration.setProperty( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "true" );
|
||||
if ( createSchema() ) {
|
||||
configuration.setProperty( Environment.HBM2DDL_AUTO, "create-drop" );
|
||||
|
|
Loading…
Reference in New Issue