org.hibernate.cache.infinispan.impl.BaseRegion Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-infinispan
Show all versions of hibernate-infinispan
A module of the Hibernate Core project
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.infinispan.impl;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
import org.infinispan.AdvancedCache;
import org.infinispan.context.Flag;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.infinispan.util.Caches;
import org.hibernate.cache.spi.Region;
import org.hibernate.cache.spi.RegionFactory;
/**
* Support for Infinispan {@link Region}s. Handles common "utility" methods for an underlying named
* Cache. In other words, this implementation doesn't actually read or write data. Subclasses are
* expected to provide core cache interaction appropriate to the semantics needed.
*
* @author Chris Bredesen
* @author Galder Zamarreño
* @since 3.5
*/
public abstract class BaseRegion implements Region {
private static final Log log = LogFactory.getLog( BaseRegion.class );
private enum InvalidateState {
INVALID, CLEARING, VALID
}
private final String name;
private final AdvancedCache regionClearCache;
private final TransactionManager tm;
private final Object invalidationMutex = new Object();
private final AtomicReference invalidateState =
new AtomicReference( InvalidateState.VALID );
private final RegionFactory factory;
protected final AdvancedCache cache;
/**
* Base region constructor.
*
* @param cache instance for the region
* @param name of the region
* @param factory for this region
*/
public BaseRegion(AdvancedCache cache, String name, RegionFactory factory) {
this.cache = cache;
this.name = name;
this.tm = cache.getTransactionManager();
this.factory = factory;
this.regionClearCache = cache.withFlags(
Flag.CACHE_MODE_LOCAL, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT
);
}
@Override
public String getName() {
return name;
}
@Override
public long getElementCountInMemory() {
if ( checkValid() ) {
return cache.size();
}
return 0;
}
/**
* {@inheritDoc}
*
* Not supported; returns -1
*/
@Override
public long getElementCountOnDisk() {
return -1;
}
/**
* {@inheritDoc}
*
* Not supported; returns -1
*/
@Override
public long getSizeInMemory() {
return -1;
}
@Override
public int getTimeout() {
// 60 seconds
return 600;
}
@Override
public long nextTimestamp() {
return factory.nextTimestamp();
}
@Override
public Map toMap() {
if ( checkValid() ) {
return cache;
}
return Collections.EMPTY_MAP;
}
@Override
public void destroy() throws CacheException {
try {
cache.stop();
}
finally {
cache.removeListener( this );
}
}
@Override
public boolean contains(Object key) {
return checkValid() && cache.containsKey( key );
}
/**
* Checks if the region is valid for operations such as storing new data
* in the region, or retrieving data from the region.
*
* @return true if the region is valid, false otherwise
*/
public boolean checkValid() {
boolean valid = isValid();
if ( !valid ) {
synchronized (invalidationMutex) {
if ( invalidateState.compareAndSet(
InvalidateState.INVALID, InvalidateState.CLEARING
) ) {
final Transaction tx = suspend();
try {
// Clear region in a separate transaction
Caches.withinTx(
cache, new Callable() {
@Override
public Void call() throws Exception {
regionClearCache.clear();
return null;
}
}
);
invalidateState.compareAndSet(
InvalidateState.CLEARING, InvalidateState.VALID
);
}
catch (Exception e) {
if ( log.isTraceEnabled() ) {
log.trace(
"Could not invalidate region: "
+ e.getLocalizedMessage()
);
}
}
finally {
resume( tx );
}
}
}
valid = isValid();
}
return valid;
}
protected boolean isValid() {
return invalidateState.get() == InvalidateState.VALID;
}
/**
* Tell the TransactionManager to suspend any ongoing transaction.
*
* @return the transaction that was suspended, or null
if
* there wasn't one
*/
public Transaction suspend() {
Transaction tx = null;
try {
if ( tm != null ) {
tx = tm.suspend();
}
}
catch (SystemException se) {
throw new CacheException( "Could not suspend transaction", se );
}
return tx;
}
/**
* Tell the TransactionManager to resume the given transaction
*
* @param tx the transaction to suspend. May be null
.
*/
public void resume(Transaction tx) {
try {
if ( tx != null ) {
tm.resume( tx );
}
}
catch (Exception e) {
throw new CacheException( "Could not resume transaction", e );
}
}
/**
* Invalidates the region.
*/
public void invalidateRegion() {
if ( log.isTraceEnabled() ) {
log.trace( "Invalidate region: " + name );
}
invalidateState.set( InvalidateState.INVALID );
}
public TransactionManager getTransactionManager() {
return tm;
}
// Used to satisfy TransactionalDataRegion.isTransactionAware in subclasses
@SuppressWarnings("unused")
public boolean isTransactionAware() {
return tm != null;
}
public AdvancedCache getCache() {
return cache;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy