HHH-4508 - Fixed 'avalable' typo

git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_3@17804 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Juraci Krohling 2009-10-20 14:21:02 +00:00
parent 1bf135296a
commit 725e2a82d9
24 changed files with 531 additions and 224 deletions

View File

@ -23,9 +23,13 @@
*/
package org.hibernate.cache.jbc2;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
@ -42,7 +46,12 @@ import org.jboss.cache.NodeSPI;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.Option;
import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.jboss.cache.notifications.annotation.CacheListener;
import org.jboss.cache.notifications.annotation.NodeInvalidated;
import org.jboss.cache.notifications.annotation.NodeModified;
import org.jboss.cache.notifications.annotation.ViewChanged;
import org.jboss.cache.notifications.event.NodeInvalidatedEvent;
import org.jboss.cache.notifications.event.NodeModifiedEvent;
import org.jboss.cache.notifications.event.ViewChangedEvent;
import org.jboss.cache.optimistic.DataVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -53,30 +62,52 @@ import org.slf4j.LoggerFactory;
*
* @author Steve Ebersole
*/
@CacheListener
public abstract class BasicRegionAdapter implements Region {
private enum InvalidateState { INVALID, CLEARING, VALID };
public static final String ITEM = CacheHelper.ITEM;
protected final Cache jbcCache;
protected final String regionName;
protected final Fqn regionFqn;
protected final Fqn internalFqn;
protected Node regionRoot;
protected final boolean optimistic;
protected final TransactionManager transactionManager;
protected final Logger log;
protected final Object regionRootMutex = new Object();
protected final Object memberId;
protected final boolean replication;
protected final Object invalidationMutex = new Object();
protected final AtomicReference<InvalidateState> invalidateState =
new AtomicReference<InvalidateState>(InvalidateState.VALID);
protected final Set<Object> currentView = new HashSet<Object>();
// protected RegionRootListener listener;
public BasicRegionAdapter(Cache jbcCache, String regionName, String regionPrefix) {
this.log = LoggerFactory.getLogger(getClass());
this.jbcCache = jbcCache;
this.transactionManager = jbcCache.getConfiguration().getRuntimeConfig().getTransactionManager();
this.regionName = regionName;
this.regionFqn = createRegionFqn(regionName, regionPrefix);
optimistic = jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC;
log = LoggerFactory.getLogger(getClass());
this.internalFqn = CacheHelper.getInternalFqn(regionFqn);
this.optimistic = jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC;
this.memberId = jbcCache.getLocalAddress();
this.replication = CacheHelper.isClusteredReplication(jbcCache);
this.jbcCache.addCacheListener(this);
synchronized (currentView) {
List view = jbcCache.getMembers();
if (view != null) {
currentView.addAll(view);
}
}
activateLocalClusterNode();
log.debug("Created Region for " + regionName + " -- regionPrefix is " + regionPrefix);
@ -129,13 +160,13 @@ public abstract class BasicRegionAdapter implements Region {
if (!regionRoot.isResident()) {
regionRoot.setResident(true);
}
establishInternalNodes();
}
catch (Exception e) {
throw new CacheException(e.getMessage(), e);
}
finally {
if (tx != null)
resume(tx);
resume(tx);
}
}
@ -154,6 +185,7 @@ public abstract class BasicRegionAdapter implements Region {
// For pessimistic locking, we just want to toss out our ref
// to any old invalid root node and get the latest (may be null)
if (!optimistic) {
establishInternalNodes();
regionRoot = jbcCache.getRoot().getChild( regionFqn );
return;
}
@ -181,6 +213,7 @@ public abstract class BasicRegionAdapter implements Region {
}
// Never evict this node
newRoot.setResident(true);
establishInternalNodes();
}
finally {
resume(tx);
@ -189,6 +222,24 @@ public abstract class BasicRegionAdapter implements Region {
}
}
private void establishInternalNodes()
{
synchronized (currentView) {
Transaction tx = suspend();
try {
for (Object member : currentView) {
DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE : null;
Fqn f = Fqn.fromRelativeElements(internalFqn, member);
CacheHelper.addNode(jbcCache, f, true, false, version);
}
}
finally {
resume(tx);
}
}
}
public String getName() {
return regionName;
}
@ -201,6 +252,11 @@ public abstract class BasicRegionAdapter implements Region {
return regionFqn;
}
public Object getMemberId()
{
return this.memberId;
}
/**
* Checks for the validity of the root cache node for this region,
* creating a new one if it does not exist or is invalid, and also
@ -219,6 +275,37 @@ public abstract class BasicRegionAdapter implements Region {
if (regionRoot != null && regionRoot.isValid() && !regionRoot.isResident())
regionRoot.setResident(true);
}
public boolean checkValid()
{
boolean valid = invalidateState.get() == InvalidateState.VALID;
if (!valid) {
synchronized (invalidationMutex) {
if (invalidateState.compareAndSet(InvalidateState.INVALID, InvalidateState.CLEARING)) {
Transaction tx = suspend();
try {
Option opt = new Option();
opt.setLockAcquisitionTimeout(1);
opt.setCacheModeLocal(true);
CacheHelper.removeAll(jbcCache, regionFqn, opt);
invalidateState.compareAndSet(InvalidateState.CLEARING, InvalidateState.VALID);
}
catch (Exception e) {
if (log.isTraceEnabled()) {
log.trace("Could not invalidate region: " + e.getLocalizedMessage());
}
}
finally {
resume(tx);
}
}
}
valid = invalidateState.get() == InvalidateState.VALID;
}
return valid;
}
public void destroy() throws CacheException {
try {
@ -242,10 +329,9 @@ public abstract class BasicRegionAdapter implements Region {
} catch (Exception e) {
throw new CacheException(e);
}
// finally {
// if (listener != null)
// jbcCache.removeCacheListener(listener);
// }
finally {
jbcCache.removeCacheListener(this);
}
}
protected void deactivateLocalNode() {
@ -256,18 +342,50 @@ public abstract class BasicRegionAdapter implements Region {
}
}
public boolean contains(Object key) {
if ( !checkValid() ) {
return false;
}
try {
Option opt = new Option();
opt.setLockAcquisitionTimeout(100);
CacheHelper.setInvocationOption( jbcCache, opt );
return CacheHelper.getAllowingTimeout( jbcCache, regionFqn, key ) != null;
}
catch ( CacheException ce ) {
throw ce;
}
catch ( Throwable t ) {
throw new CacheException( t );
}
}
public long getSizeInMemory() {
// not supported
return -1;
}
public long getElementCountInMemory() {
try {
Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
return childrenNames.size();
} catch (Exception e) {
throw new CacheException(e);
if (checkValid()) {
try {
Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
int size = childrenNames.size();
if (childrenNames.contains(CacheHelper.Internal.NODE)) {
size--;
}
return size;
}
catch ( CacheException ce ) {
throw ce;
}
catch (Exception e) {
throw new CacheException(e);
}
}
else {
return 0;
}
}
public long getElementCountOnDisk() {
@ -275,17 +393,24 @@ public abstract class BasicRegionAdapter implements Region {
}
public Map toMap() {
try {
Map result = new HashMap();
Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
for (Object childName : childrenNames) {
result.put(childName, CacheHelper.get(jbcCache,regionFqn, childName));
}
return result;
} catch (CacheException e) {
throw e;
} catch (Exception e) {
throw new CacheException(e);
if (checkValid()) {
try {
Map result = new HashMap();
Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
for (Object childName : childrenNames) {
if (CacheHelper.Internal.NODE != childName) {
result.put(childName, CacheHelper.get(jbcCache,regionFqn, childName));
}
}
return result;
} catch (CacheException e) {
throw e;
} catch (Exception e) {
throw new CacheException(e);
}
}
else {
return Collections.emptyMap();
}
}
@ -327,7 +452,7 @@ public abstract class BasicRegionAdapter implements Region {
* @return the transaction that was suspended, or <code>null</code> if
* there wasn't one
*/
protected Transaction suspend() {
public Transaction suspend() {
Transaction tx = null;
try {
if (transactionManager != null) {
@ -345,7 +470,7 @@ public abstract class BasicRegionAdapter implements Region {
* @param tx
* the transaction to suspend. May be <code>null</code>.
*/
protected void resume(Transaction tx) {
public void resume(Transaction tx) {
try {
if (tx != null)
transactionManager.resume(tx);
@ -404,17 +529,52 @@ public abstract class BasicRegionAdapter implements Region {
return escaped;
}
// @CacheListener
// public class RegionRootListener {
//
// @NodeCreated
// public void nodeCreated(NodeCreatedEvent event) {
// if (!event.isPre() && event.getFqn().equals(getRegionFqn())) {
// log.debug("Node created for " + getRegionFqn());
// Node regionRoot = jbcCache.getRoot().getChild(getRegionFqn());
// regionRoot.setResident(true);
// }
// }
//
// }
@NodeModified
public void nodeModified(NodeModifiedEvent event)
{
handleEvictAllModification(event);
}
protected boolean handleEvictAllModification(NodeModifiedEvent event) {
if (!event.isPre() && (replication || event.isOriginLocal()) && event.getData().containsKey(ITEM))
{
if (event.getFqn().isChildOf(internalFqn))
{
invalidateState.set(InvalidateState.INVALID);
return true;
}
}
return false;
}
@NodeInvalidated
public void nodeInvalidated(NodeInvalidatedEvent event)
{
handleEvictAllInvalidation(event);
}
protected boolean handleEvictAllInvalidation(NodeInvalidatedEvent event)
{
if (!event.isPre() && event.getFqn().isChildOf(internalFqn))
{
invalidateState.set(InvalidateState.INVALID);
return true;
}
return false;
}
@ViewChanged
public void viewChanged(ViewChangedEvent event) {
synchronized (currentView) {
List view = event.getNewView().getMembers();
if (view != null) {
currentView.addAll(view);
establishInternalNodes();
}
}
}
}

View File

@ -23,11 +23,12 @@
*/
package org.hibernate.cache.jbc2.access;
import javax.transaction.Transaction;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.jbc2.BasicRegionAdapter;
import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
import org.hibernate.cache.jbc2.util.CacheHelper;
import org.hibernate.cache.jbc2.util.DataVersionAdapter;
@ -75,22 +76,17 @@ public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDe
* by adding a {@link NonLockingDataVersion} to the invocation.
*/
@Override
public void evictAll() throws CacheException {
evictOrRemoveAll();
}
/**
* Overrides the {@link TransactionalAccessDelegate#get(Object, long) superclass}
* by {@link BasicRegionAdapter#ensureRegionRootExists() ensuring the root
* node for the region exists} before making the call.
*/
@Override
public Object get(Object key, long txTimestamp) throws CacheException
public void evictAll() throws CacheException
{
region.ensureRegionRootExists();
return CacheHelper.get(cache, regionFqn, key);
Transaction tx = region.suspend();
try {
region.ensureRegionRootExists();
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.sendEvictAllNotification(cache, regionFqn, region.getMemberId(), opt);
}
finally {
region.resume(tx);
}
}
/**
@ -100,6 +96,9 @@ public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDe
*/
@Override
public boolean insert(Object key, Object value, Object version) throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
@ -111,6 +110,9 @@ public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDe
@Override
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
@ -123,6 +125,9 @@ public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDe
@Override
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
@ -132,6 +137,10 @@ public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDe
@Override
public void remove(Object key) throws CacheException {
// We remove whether or not the region is valid. Other nodes
// may have already restored the region so they need to
// be informed of the change.
region.ensureRegionRootExists();
@ -141,14 +150,18 @@ public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDe
@Override
public void removeAll() throws CacheException {
evictOrRemoveAll();
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.removeAll(cache, regionFqn, opt);
}
@Override
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
// We update whether or not the region is valid. Other nodes
// may have already restored the region so they need to
// be informed of the change.
region.ensureRegionRootExists();
Option opt = getDataVersionOption(currentVersion, previousVersion);
@ -166,10 +179,4 @@ public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDe
return opt;
}
private void evictOrRemoveAll() {
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.removeAll(cache, regionFqn, opt);
}
}

View File

@ -23,6 +23,8 @@
*/
package org.hibernate.cache.jbc2.access;
import javax.transaction.Transaction;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
@ -56,13 +58,19 @@ public class TransactionalAccessDelegate {
}
public Object get(Object key, long txTimestamp) throws CacheException {
if (!region.checkValid())
return null;
region.ensureRegionRootExists();
return CacheHelper.get(cache, regionFqn, key);
}
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
@ -72,6 +80,9 @@ public class TransactionalAccessDelegate {
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
// We ignore minimalPutOverride. JBossCache putForExternalRead is
@ -96,6 +107,9 @@ public class TransactionalAccessDelegate {
public boolean insert(Object key, Object value, Object version) throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
CacheHelper.put(cache, regionFqn, key, value);
@ -109,6 +123,10 @@ public class TransactionalAccessDelegate {
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
// We update whether or not the region is valid. Other nodes
// may have already restored the region so they need to
// be informed of the change.
region.ensureRegionRootExists();
CacheHelper.put(cache, regionFqn, key, value);
@ -122,13 +140,17 @@ public class TransactionalAccessDelegate {
public void remove(Object key) throws CacheException {
// We remove whether or not the region is valid. Other nodes
// may have already restored the region so they need to
// be informed of the change.
region.ensureRegionRootExists();
CacheHelper.remove(cache, regionFqn, key);
}
public void removeAll() throws CacheException {
evictOrRemoveAll();
CacheHelper.removeAll(cache, regionFqn);
}
public void evict(Object key) throws CacheException {
@ -139,10 +161,15 @@ public class TransactionalAccessDelegate {
}
public void evictAll() throws CacheException {
evictOrRemoveAll();
Transaction tx = region.suspend();
try {
region.ensureRegionRootExists();
CacheHelper.sendEvictAllNotification(cache, regionFqn, region.getMemberId(), null);
}
finally {
region.resume(tx);
}
}
private void evictOrRemoveAll() throws CacheException {
CacheHelper.removeAll(cache, regionFqn);
}
}

View File

@ -26,6 +26,7 @@ package org.hibernate.cache.jbc2.collection;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.jboss.cache.notifications.annotation.CacheListener;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
@ -39,6 +40,7 @@ import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
*
* @author Steve Ebersole
*/
@CacheListener
public class CollectionRegionImpl extends TransactionalDataRegionAdapter implements CollectionRegion {
public static final String TYPE = "COLL";

View File

@ -26,6 +26,7 @@ package org.hibernate.cache.jbc2.entity;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.jboss.cache.notifications.annotation.CacheListener;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
@ -39,6 +40,7 @@ import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
*
* @author Steve Ebersole
*/
@CacheListener
public class EntityRegionImpl extends TransactionalDataRegionAdapter implements EntityRegion {
public static final String TYPE = "ENTITY";

View File

@ -25,6 +25,8 @@ package org.hibernate.cache.jbc2.query;
import java.util.Properties;
import javax.transaction.Transaction;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
@ -33,6 +35,7 @@ import org.hibernate.util.PropertiesHelper;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.Option;
import org.jboss.cache.notifications.annotation.CacheListener;
/**
* Defines the behavior of the query cache regions for JBossCache 2.x.
@ -40,6 +43,7 @@ import org.jboss.cache.config.Option;
* @author Brian Stansberry
* @version $Revision$
*/
@CacheListener
public class QueryResultsRegionImpl extends TransactionalDataRegionAdapter implements QueryResultsRegion {
public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.region.jbc2.query.localonly";
@ -85,14 +89,22 @@ public class QueryResultsRegionImpl extends TransactionalDataRegionAdapter imple
}
public void evictAll() throws CacheException {
Option opt = getNonLockingDataVersionOption(false);
if (localOnly)
opt.setCacheModeLocal(true);
CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
Transaction tx = suspend();
try {
ensureRegionRootExists();
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.sendEvictAllNotification(jbcCache, regionFqn, getMemberId(), opt);
}
finally {
resume(tx);
}
}
public Object get(Object key) throws CacheException {
if (!checkValid())
return null;
ensureRegionRootExists();
// Don't hold the JBC node lock throughout the tx, as that
@ -106,28 +118,30 @@ public class QueryResultsRegionImpl extends TransactionalDataRegionAdapter imple
public void put(Object key, Object value) throws CacheException {
ensureRegionRootExists();
// Here we don't want to suspend the tx. If we do:
// 1) We might be caching query results that reflect uncommitted
// changes. No tx == no WL on cache node, so other threads
// can prematurely see those query results
// 2) No tx == immediate replication. More overhead, plus we
// spread issue #1 above around the cluster
// Add a zero (or quite low) timeout option so we don't block.
// Ignore any TimeoutException. Basically we forego caching the
// query result in order to avoid blocking.
// Reads are done with suspended tx, so they should not hold the
// lock for long. Not caching the query result is OK, since
// any subsequent read will just see the old result with its
// out-of-date timestamp; that result will be discarded and the
// db query performed again.
Option opt = getNonLockingDataVersionOption(false);
opt.setLockAcquisitionTimeout(2);
if (localOnly)
opt.setCacheModeLocal(true);
CacheHelper.putAllowingTimeout(getCacheInstance(), getRegionFqn(), key, value, opt);
if (checkValid()) {
ensureRegionRootExists();
// Here we don't want to suspend the tx. If we do:
// 1) We might be caching query results that reflect uncommitted
// changes. No tx == no WL on cache node, so other threads
// can prematurely see those query results
// 2) No tx == immediate replication. More overhead, plus we
// spread issue #1 above around the cluster
// Add a zero (or quite low) timeout option so we don't block.
// Ignore any TimeoutException. Basically we forego caching the
// query result in order to avoid blocking.
// Reads are done with suspended tx, so they should not hold the
// lock for long. Not caching the query result is OK, since
// any subsequent read will just see the old result with its
// out-of-date timestamp; that result will be discarded and the
// db query performed again.
Option opt = getNonLockingDataVersionOption(false);
opt.setLockAcquisitionTimeout(2);
if (localOnly)
opt.setCacheModeLocal(true);
CacheHelper.putAllowingTimeout(getCacheInstance(), getRegionFqn(), key, value, opt);
}
}
@Override

View File

@ -41,6 +41,7 @@ import org.jboss.cache.config.Option;
import org.jboss.cache.notifications.annotation.CacheListener;
import org.jboss.cache.notifications.annotation.NodeModified;
import org.jboss.cache.notifications.annotation.NodeRemoved;
import org.jboss.cache.notifications.event.NodeInvalidatedEvent;
import org.jboss.cache.notifications.event.NodeModifiedEvent;
import org.jboss.cache.notifications.event.NodeRemovedEvent;
@ -95,14 +96,21 @@ public class TimestampsRegionImpl extends TransactionalDataRegionAdapter impleme
public void evictAll() throws CacheException {
// TODO Is this a valid operation on a timestamps cache?
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
Transaction tx = suspend();
try {
ensureRegionRootExists();
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.sendEvictAllNotification(jbcCache, regionFqn, getMemberId(), opt);
}
finally {
resume(tx);
}
}
public Object get(Object key) throws CacheException {
Object value = localCache.get(key);
if (value == null) {
if (value == null && checkValid()) {
ensureRegionRootExists();
@ -147,14 +155,15 @@ public class TimestampsRegionImpl extends TransactionalDataRegionAdapter impleme
*/
@NodeModified
public void nodeModified(NodeModifiedEvent event) {
if (event.isPre())
return;
Fqn fqn = event.getFqn();
Fqn regFqn = getRegionFqn();
if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
Object key = fqn.get(regFqn.size());
localCache.put(key, event.getData().get(ITEM));
if (!handleEvictAllModification(event) && !event.isPre()) {
Fqn fqn = event.getFqn();
Fqn regFqn = getRegionFqn();
if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
Object key = fqn.get(regFqn.size());
localCache.put(key, event.getData().get(ITEM));
}
}
}
@ -178,8 +187,30 @@ public class TimestampsRegionImpl extends TransactionalDataRegionAdapter impleme
localCache.clear();
}
}
/**
@Override
protected boolean handleEvictAllInvalidation(NodeInvalidatedEvent event)
{
boolean result = super.handleEvictAllInvalidation(event);
if (result) {
localCache.clear();
}
return result;
}
@Override
protected boolean handleEvictAllModification(NodeModifiedEvent event)
{
boolean result = super.handleEvictAllModification(event);
if (result) {
localCache.clear();
}
return result;
}
/**
* Brings all data from the distributed cache into our local cache.
*/
private void populateLocalCache() {

View File

@ -46,6 +46,8 @@ import org.slf4j.LoggerFactory;
*/
public class CacheHelper {
public static enum Internal { NODE, LOCAL };
/** Key under which items are cached */
public static final String ITEM = "item";
/** Key and value used in a hack to create region root nodes */
@ -467,4 +469,23 @@ public class CacheHelper {
option.setDataVersion(version);
setInvocationOption(cache, option);
}
public static Fqn getInternalFqn(Fqn region)
{
return Fqn.fromRelativeElements(region, Internal.NODE);
}
public static void sendEvictNotification(Cache cache, Fqn region, Object member, Object key, Option option)
{
setInvocationOption(cache, option);
Fqn f = Fqn.fromRelativeElements(region, Internal.NODE, member == null ? Internal.LOCAL : member, key);
cache.put(f, ITEM, DUMMY);
}
public static void sendEvictAllNotification(Cache cache, Fqn region, Object member, Option option)
{
setInvocationOption(cache, option);
Fqn f = Fqn.fromRelativeElements(region, Internal.NODE, member == null ? Internal.LOCAL : member);
cache.put(f, ITEM, DUMMY);
}
}

View File

@ -116,6 +116,11 @@ public class DataVersionAdapter implements DataVersion {
// treat as us being newer
return (other.previousVersion != null);
}
// Can't be newer than itself
if ( this == dataVersion ) {
return false;
}
return versionComparator.compare(currentVersion, other.previousVersion) >= 1;
}

View File

@ -24,9 +24,7 @@
package org.hibernate.test.cache.jbc2;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.GeneralDataRegion;
import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.Region;
@ -171,8 +169,7 @@ public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionIm
Node regionRoot = localCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
Set children = regionRoot.getChildrenNames();
assertEquals("No children in " + children, 0, children.size());
assertEquals("No children in " + regionRoot, 0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (optimistic) {
@ -181,7 +178,7 @@ public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionIm
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertEquals(0, regionRoot.getChildrenNames().size());
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (optimistic) {
@ -212,35 +209,24 @@ public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionIm
localRegion.evictAll();
// This should re-establish the region root node in the optimistic case
// This should re-establish the region root node
assertNull(localRegion.get(KEY));
regionRoot = localCache.getRoot().getChild(regionFqn);
if (optimistic) {
assertFalse(regionRoot == null);
assertEquals(0, regionRoot.getChildrenNames().size());
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
}
else {
assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
}
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish
// This only adds a node in the case of optimistic locking
assertEquals(null, remoteRegion.get(KEY));
regionRoot = remoteCache.getRoot().getChild(regionFqn);
if (optimistic) {
assertFalse(regionRoot == null);
assertEquals(0, regionRoot.getChildrenNames().size());
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
}
else {
assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
}
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
assertEquals("local is clean", null, localRegion.get(KEY));
assertEquals("remote is clean", null, remoteRegion.get(KEY));

View File

@ -25,10 +25,14 @@ package org.hibernate.test.cache.jbc2;
import java.util.Set;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.jbc2.util.CacheHelper;
import org.hibernate.junit.UnitTestCase;
import org.hibernate.test.util.CacheTestSupport;
import org.jboss.cache.Cache;
import org.jboss.cache.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -96,4 +100,15 @@ public abstract class AbstractJBossCacheTestCase extends UnitTestCase {
protected void avoidConcurrentFlush() {
testSupport.avoidConcurrentFlush();
}
protected int getValidChildrenCount(Node node) {
int result = 0;
Set<Node> children = node.getChildren();
for (Node child : children) {
if (node.isValid() && CacheHelper.Internal.NODE.equals(child.getFqn().getLastElement()) == false) {
result++;
}
}
return result;
}
}

View File

@ -471,38 +471,27 @@ public abstract class AbstractCollectionRegionAccessStrategyTestCase extends Abs
localAccessStrategy.evictAll();
else
localAccessStrategy.removeAll();
// This should re-establish the region root node in the optimistic case
// This should re-establish the region root node
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
regionRoot = localCache.getRoot().getChild(regionFqn);
if (isUsingOptimisticLocking()) {
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
}
else {
assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
}
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish
// This only adds a node in the case of optimistic locking
assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
regionRoot = remoteCache.getRoot().getChild(regionFqn);
if (isUsingOptimisticLocking()) {
assertFalse(regionRoot == null);
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Not invalidation, so we didn't insert a child above
assertEquals(0, getValidChildrenCount(regionRoot));
}
else {
assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
}
assertFalse(regionRoot == null);
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Not invalidation, so we didn't insert a child above
assertEquals(0, getValidChildrenCount(regionRoot));
// Test whether the get above messes up the optimistic version
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
@ -521,17 +510,7 @@ public abstract class AbstractCollectionRegionAccessStrategyTestCase extends Abs
assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
private int getValidChildrenCount(Node node) {
int result = 0;
for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
if (((Node) it.next()).isValid()) {
result++;
}
}
return result;
}
private void rollback() {
try {
BatchModeTransactionManager.getInstance().rollback();

View File

@ -682,36 +682,26 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
else
localAccessStrategy.removeAll();
// This should re-establish the region root node in the optimistic case
// This should re-establish the region root node
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
regionRoot = localCache.getRoot().getChild(regionFqn);
if (isUsingOptimisticLocking()) {
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
}
else {
assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
}
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish
assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
regionRoot = remoteCache.getRoot().getChild(regionFqn);
if (isUsingOptimisticLocking()) {
assertFalse(regionRoot == null);
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Not invalidation, so we didn't insert a child above
assertEquals(0, getValidChildrenCount(regionRoot));
}
else {
assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
}
assertFalse(regionRoot == null);
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Not invalidation, so we didn't insert a child above
assertEquals(0, getValidChildrenCount(regionRoot));
// Test whether the get above messes up the optimistic version
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
@ -730,17 +720,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
private int getValidChildrenCount(Node node) {
int result = 0;
for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
if (((Node) it.next()).isValid()) {
result++;
}
}
return result;
}
protected void rollback() {
try {
BatchModeTransactionManager.getInstance().rollback();

View File

@ -63,7 +63,7 @@ public abstract class AbstractTransactionalAccessTestCase extends AbstractEntity
final CountDownLatch commitLatch = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(1);
Thread blocker = new Thread() {
Thread blocker = new Thread("Blocker") {
public void run() {
@ -95,7 +95,7 @@ public abstract class AbstractTransactionalAccessTestCase extends AbstractEntity
}
};
Thread putter = new Thread() {
Thread putter = new Thread("Putter") {
public void run() {

View File

@ -26,11 +26,11 @@ import java.util.List;
import java.util.Set;
import org.hibernate.FlushMode;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.test.cache.jbc2.functional.CacheTestCaseBase;
import org.hibernate.test.cache.jbc2.functional.Contact;
import org.hibernate.test.cache.jbc2.functional.Customer;
@ -90,7 +90,12 @@ extends CacheTestCaseBase
assertNotNull("Red Hat contacts exist", rhContacts);
assertEquals("Created expected number of Red Hat contacts", 10, rhContacts.size());
SecondLevelCacheStatistics contactSlcs = getEnvironment().getSessionFactory().getStatistics().getSecondLevelCacheStatistics(
getPrefixedRegionName(Contact.class.getName()));
assertEquals(contactSlcs.getElementCountInMemory(), 20);
assertEquals("Deleted all Red Hat contacts", 10, deleteContacts());
assertEquals(0, contactSlcs.getElementCountInMemory());
List<Integer> jbContacts = getContactsByCustomer("JBoss");
assertNotNull("JBoss contacts exist", jbContacts);
@ -108,6 +113,7 @@ extends CacheTestCaseBase
}
updateContacts("Kabir", "Updated");
assertEquals(contactSlcs.getElementCountInMemory(), 0);
for (Integer id : jbContacts)
{
Contact contact = getContact(id);
@ -120,6 +126,21 @@ extends CacheTestCaseBase
List<Integer> updated = getContactsByTLF("Updated");
assertNotNull("Got updated contacts", updated);
assertEquals("Updated contacts", 5, updated.size());
updateContactsWithOneManual("Kabir", "UpdatedAgain");
assertEquals(contactSlcs.getElementCountInMemory(), 0);
for (Integer id : jbContacts)
{
Contact contact = getContact(id);
assertNotNull("JBoss contact " + id + " exists", contact);
String expected = ("Kabir".equals(contact.getName())) ? "UpdatedAgain" : "2222";
assertEquals("JBoss contact " + id + " has correct TLF",
expected, contact.getTlf());
}
updated = getContactsByTLF("UpdatedAgain");
assertNotNull("Got updated contacts", updated);
assertEquals("Updated contacts", 5, updated.size());
}
finally
{
@ -231,6 +252,34 @@ extends CacheTestCaseBase
throw e;
}
}
public int updateContactsWithOneManual(String name, String newTLF) throws Exception
{
String queryHQL = "from Contact c where c.name = :cName";
String updateHQL = "update Contact set tlf = :cNewTLF where name = :cName";
SimpleJtaTransactionManagerImpl.getInstance().begin();
try {
Session session = getSessions().getCurrentSession();
@SuppressWarnings("unchecked")
List<Contact> list = session.createQuery(queryHQL).setParameter("cName", name).list();
list.get(0).setTlf(newTLF);
int rowsAffected = session.createQuery(updateHQL)
.setFlushMode(FlushMode.AUTO)
.setParameter("cNewTLF", newTLF)
.setParameter("cName", name)
.executeUpdate();
SimpleJtaTransactionManagerImpl.getInstance().commit();
return rowsAffected;
}
catch (Exception e) {
SimpleJtaTransactionManagerImpl.getInstance().rollback();
throw e;
}
}
public Contact getContact(Integer id) throws Exception
{

View File

@ -124,10 +124,10 @@
Number of milliseconds to wait until all responses for a
synchronous call have been received.
-->
<attribute name="SyncReplTimeout">20000</attribute>
<attribute name="SyncReplTimeout">10000</attribute>
<!-- Max number of milliseconds to wait for a lock acquisition -->
<attribute name="LockAcquisitionTimeout">15000</attribute>
<attribute name="LockAcquisitionTimeout">5000</attribute>
<!--
Indicate whether to use marshalling or not. Set this to true if you are running under a scoped

View File

@ -105,10 +105,10 @@
Number of milliseconds to wait until all responses for a
synchronous call have been received.
-->
<attribute name="SyncReplTimeout">20000</attribute>
<attribute name="SyncReplTimeout">10000</attribute>
<!-- Max number of milliseconds to wait for a lock acquisition -->
<attribute name="LockAcquisitionTimeout">15000</attribute>
<attribute name="LockAcquisitionTimeout">5000</attribute>
<!-- Specific eviction policy configurations. This is LRU -->
<attribute name="EvictionPolicyConfig">

View File

@ -46,10 +46,6 @@ public class BytecodeProviderImpl implements BytecodeProvider {
private static final Logger log = LoggerFactory.getLogger( BytecodeProviderImpl.class );
public BytecodeProviderImpl() {
log.warn( "The CGLIB BytecodeProvider impl is considered deprecated and not recommended for use" );
}
public ProxyFactoryFactory getProxyFactoryFactory() {
return new ProxyFactoryFactoryImpl();
}

View File

@ -1089,6 +1089,15 @@ public abstract class Dialect {
return "";
}
/**
* Command used to drop a temporary table.
*
* @return The command used to drop a temporary table.
*/
public String getDropTemporaryTableString() {
return "drop table";
}
/**
* Does the dialect require that temporary table DDL statements occur in
* isolation from other statements? This would be the case if the creation

View File

@ -278,6 +278,16 @@ public class MySQLDialect extends Dialect {
return "create temporary table if not exists";
}
public String getDropTemporaryTableString() {
return "drop temporary table";
}
public Boolean performTemporaryTableDDLInIsolation() {
// because we [drop *temporary* table...] we do not
// have to perform these in isolation.
return Boolean.FALSE;
}
public String getCastTypeName(int code) {
if ( code==Types.INTEGER ) {
return "signed";
@ -321,10 +331,6 @@ public class MySQLDialect extends Dialect {
return true;
}
public Boolean performTemporaryTableDDLInIsolation() {
return Boolean.FALSE;
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -104,7 +104,7 @@ public class DialectFactory {
public static Dialect buildDialect(Properties properties) {
String dialectName = properties.getProperty( Environment.DIALECT );
if ( dialectName == null ) {
throw new HibernateException( "'hibernate.dialect' must be set when no Connection avalable" );
throw new HibernateException( "'hibernate.dialect' must be set when no Connection available" );
}
return constructDialect( dialectName );
}

View File

@ -181,8 +181,10 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
public void doWork(Connection connection) throws HibernateException {
Statement stmnt = null;
try {
final String command = session.getFactory().getSettings().getDialect().getDropTemporaryTableString()
+ " " + persister.getTemporaryIdTableName();
stmnt = connection.createStatement();
stmnt.executeUpdate( "drop table " + persister.getTemporaryIdTableName() );
stmnt.executeUpdate( command );
}
catch( Throwable t ) {
log.warn( "unable to drop temporary id table after use [" + t.getMessage() + "]" );

View File

@ -158,9 +158,9 @@
<para>
Commercial development support, production support, and training for Hibernate is
available through Red Hat Inc. (see http://www.hibernate.org/SupportTraining/).
available through Red Hat, Inc. (see http://www.hibernate.org/SupportTraining/).
Hibernate is a Professional Open Source project and a critical component of the
JBoss Enterprise Middleware System (JEMS) suite of products.
JBoss Enterprise Application Platform.
</para>
</preface>

View File

@ -198,12 +198,30 @@
</plugin>
</plugins>
</pluginManagement>
<extensions>
<!-- webdav based deployments (snapshot repo) -->
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav</artifactId>
<version>1.0-beta-2</version>
</extension>
<!-- scm based deployments (release repo) -->
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-scm</artifactId>
<version>1.0-beta-6</version>
</extension>
<extension>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-manager-plexus</artifactId>
<version>1.0</version>
</extension>
<extension>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-provider-svnexe</artifactId>
<version>1.0</version>
</extension>
</extensions>
</build>
@ -351,11 +369,9 @@
<distributionManagement>
<repository>
<!-- Copy the dist to the local checkout of the JBoss maven2 repo ${maven.repository.root} -->
<!-- It is anticipated that ${maven.repository.root} be set in user's settings.xml -->
<!-- todo : replace this with direct svn access once the svnkit providers are available -->
<id>repository.jboss.org</id>
<url>file://${maven.repository.root}</url>
<name>JBoss Release Repository</name>
<url>scm:svn:https://svn.jboss.org/repos/repository.jboss.org/maven2</url>
</repository>
<snapshotRepository>
<id>snapshots.jboss.org</id>