HHH-5647 - Develop release process using Gradle

This commit is contained in:
Steve Ebersole 2010-10-12 15:39:33 -05:00
parent bea71a4562
commit d2c88d55df
174 changed files with 768 additions and 22481 deletions

1
.gitignore vendored
View File

@ -1,6 +1,5 @@
.gradle
target
build
.idea
.idea/*
*.ipr

View File

@ -45,7 +45,7 @@ libraries = [
dom4j: 'dom4j:dom4j:1.6.1@jar',
// h2
h2: 'com.h2database:h2:1.2.134',
h2: 'com.h2database:h2:1.2.140',
// Javassist
javassist: 'javassist:javassist:3.12.0.GA',
@ -75,20 +75,20 @@ libraries = [
subprojects { subProject ->
apply plugin: 'idea'
apply { url: 'https://loom.svn.sourceforge.net/svnroot/loom/shared/trunk/artifacts.gradle' } // sets up source and javadoc jar uploads
apply plugin: 'maven'
defaultTasks 'build'
group = 'org.hibernate'
version = '4.0.0-SNAPSHOT'
defaultTasks 'build'
// minimize changes, at least for now (gradle uses 'build' by default)..
buildDir = "target"
if ( ! subProject.name.startsWith( 'hibernate-release' ) ) {
if ( ! subProject.name.startsWith( 'release' ) ) {
apply plugin: 'java'
apply plugin: 'maven' // for install task as well as deploy dependencies
// apply plugin: org.hibernate.build.gradle.upload.UploadManager
apply plugin: org.hibernate.build.gradle.upload.UploadManager
configurations {
provided {
@ -128,7 +128,6 @@ subprojects { subProject ->
)
test {
// ignoreFailures = true
systemProperties['hibernate.test.validatefailureexpected'] = true
maxHeapSize = "1024m"
}
@ -193,46 +192,25 @@ subprojects { subProject ->
pom.project pomConfig
}
if ( ! project.hasProperty('JBOSS_NEXUS_USERNAME') ) {
JBOSS_NEXUS_USERNAME = "";
}
if ( ! project.hasProperty('JBOSS_NEXUS_PASSWORD') ) {
JBOSS_NEXUS_PASSWORD = "";
}
uploadArchives {
repositories.mavenDeployer {
name = 'jbossDeployer'
configuration = configurations.deployerJars
pom.project pomConfig
// repository(url: "https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/")
// snapshotRepository(url: "https://repository.jboss.org/nexus/content/repositories/snapshots")
credentials = [userName: JBOSS_NEXUS_USERNAME, password: JBOSS_NEXUS_PASSWORD]
repository(url: "https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/") {
authentication(credentials)
}
snapshotRepository(url: "https://repository.jboss.org/nexus/content/repositories/snapshots") {
authentication(credentials)
}
repository(url: "https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/")
snapshotRepository(url: "https://repository.jboss.org/nexus/content/repositories/snapshots")
}
}
task javadocJar(type: Jar, dependsOn: javadoc) {
from javadoc.destinationDir
classifier = 'javadoc'
}
task sourcesJar(type: Jar, dependsOn: compileJava) {
from sourceSets.main.allSource
classifier = 'sources'
}
artifacts {
archives javadocJar
archives sourcesJar
}
uploadArchives.dependsOn javadocJar
uploadArchives.dependsOn sourcesJar
}

View File

@ -1,6 +1,8 @@
apply plugin: 'groovy'
apply plugin: 'idea'
buildDir = "target"
repositories {
mavenCentral()
mavenRepo urls: "file://" + System.getProperty('user.home') + "/.m2/repository/"
@ -15,4 +17,7 @@ dependencies {
compile 'org.apache.maven.wagon:wagon-http:1.0-beta-6'
groovy localGroovy()
}
ideaModule {
}

View File

@ -0,0 +1,78 @@
/*
* 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.build.gradle.javadoc
import org.gradle.api.tasks.SourceSet
import org.gradle.api.Project
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
class Aggregator {
private final Javadoc javadocTask;
private Set<String> excludedSourceSetNames;
public Aggregator(Javadoc javadocTask) {
this.javadocTask = javadocTask;
}
private Set<String> getExcludedSourceSetNames() {
if ( excludedSourceSetNames == null ) {
excludedSourceSetNames = new HashSet<String>();
}
return excludedSourceSetNames;
}
/**
* Allow adding them one by one
*
*/
public void excludeSourceSetName(String name) {
getExcludedSourceSetNames().add( name );
}
/**
* Also, allow adding them all at once
*/
public void excludeSourceSetNames(String[] names) {
getExcludedSourceSetNames().addAll( Arrays.asList( names ) );
}
public void project(Project project) {
project.sourceSets.each { SourceSet sourceSet ->
if ( excludedSourceSetNames == null || !excludedSourceSetNames.contains( sourceSet.name ) ) {
javadocTask.source sourceSet.allJava
if( javadocTask.classpath ) {
javadocTask.classpath += sourceSet.classes + sourceSet.compileClasspath
}
else {
javadocTask.classpath = sourceSet.classes + sourceSet.compileClasspath
}
}
}
}
}

View File

@ -0,0 +1,259 @@
/*
* 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.build.gradle.javadoc
import org.gradle.process.internal.ExecAction
import org.gradle.process.internal.ExecException
import org.gradle.api.GradleException
import org.gradle.external.javadoc.JavadocExecHandleBuilder
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.api.tasks.TaskAction
import org.gradle.api.file.FileCollection
import org.gradle.external.javadoc.MinimalJavadocOptions
import org.gradle.plugins.idea.model.Jdk
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.SourceTask
import org.gradle.util.ConfigureUtil
import org.gradle.util.GUtil
/**
* This is largely a merging of the different classes in standard Gradle needed to perform Javadoc generation.
*
* @author Steve Ebersole
*/
class Javadoc extends SourceTask {
private JavadocExecHandleBuilder javadocExecHandleBuilder = new JavadocExecHandleBuilder();
private Jdk jdk;
private File destinationDir;
private boolean failOnError = true;
private String title;
private String maxMemory;
private MinimalJavadocOptions options = new StandardJavadocDocletOptions();
// EmptyFileCollection not available in my project as is
// private FileCollection classpath = new EmptyFileCollection();
private FileCollection classpath;
private String executable;
@TaskAction
protected void generate() {
final File destinationDir = getDestinationDir();
if ( options.getDestinationDirectory() == null ) {
options.destinationDirectory(destinationDir);
}
options.classpath(new ArrayList<File>(getClasspath().getFiles()));
if ( jdk != null ) {
executable = jdk.getJavadocExecutable()
}
if ( !GUtil.isTrue(options.getWindowTitle()) && GUtil.isTrue(getTitle()) ) {
options.windowTitle(getTitle());
}
if ( options instanceof StandardJavadocDocletOptions ) {
StandardJavadocDocletOptions docletOptions = (StandardJavadocDocletOptions) options;
if ( !GUtil.isTrue(docletOptions.getDocTitle()) && GUtil.isTrue(getTitle()) ) {
docletOptions.setDocTitle(getTitle());
}
}
if ( maxMemory != null ) {
final List<String> jFlags = options.getJFlags();
final Iterator<String> jFlagsIt = jFlags.iterator();
boolean containsXmx = false;
while ( !containsXmx && jFlagsIt.hasNext() ) {
final String jFlag = jFlagsIt.next();
if ( jFlag.startsWith("-Xmx") ) {
containsXmx = true;
}
}
if ( !containsXmx ) {
options.jFlags("-Xmx" + maxMemory);
}
}
List<String> sourceNames = new ArrayList<String>();
for ( File sourceFile: getSource() ) {
sourceNames.add(sourceFile.getAbsolutePath());
}
options.setSourceNames(sourceNames);
executeExternalJavadoc();
}
private void executeExternalJavadoc() {
javadocExecHandleBuilder.execDirectory(getProject().getRootDir()).options(options).optionsFile(getOptionsFile());
ExecAction execAction = javadocExecHandleBuilder.getExecHandle();
if ( executable != null && executable.length() > 0 ) {
execAction.setExecutable(executable);
}
if ( !failOnError ) {
execAction.setIgnoreExitValue(true);
}
try {
execAction.execute();
}
catch (ExecException e) {
throw new GradleException("Javadoc generation failed.", e);
}
}
void setJavadocExecHandleBuilder(JavadocExecHandleBuilder javadocExecHandleBuilder) {
if (javadocExecHandleBuilder == null) {
throw new IllegalArgumentException("javadocExecHandleBuilder == null!");
}
this.javadocExecHandleBuilder = javadocExecHandleBuilder;
}
/**
* <p>Returns the directory to generate the documentation into.</p>
*
* @return The directory.
*/
@OutputDirectory
public File getDestinationDir() {
return destinationDir;
}
/**
* <p>Sets the directory to generate the documentation into.</p>
*/
public void setDestinationDir(File destinationDir) {
this.destinationDir = destinationDir;
}
/**
* Returns the amount of memory allocated to this task.
*/
public String getMaxMemory() {
return maxMemory;
}
/**
* Sets the amount of memory allocated to this task.
*
* @param maxMemory The amount of memory
*/
public void setMaxMemory(String maxMemory) {
this.maxMemory = maxMemory;
}
/**
* <p>Returns the title for the generated documentation.</p>
*
* @return The title, possibly null.
*/
public String getTitle() {
return title;
}
/**
* <p>Sets the title for the generated documentation.</p>
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Returns whether javadoc generation is accompanied by verbose output.
*
* @see #setVerbose(boolean)
*/
public boolean isVerbose() {
return options.isVerbose();
}
/**
* Sets whether javadoc generation is accompanied by verbose output or not. The verbose output is done via println
* (by the underlying ant task). Thus it is not catched by our logging.
*
* @param verbose Whether the output should be verbose.
*/
public void setVerbose(boolean verbose) {
if ( verbose ) {
options.verbose();
}
}
@InputFiles
public FileCollection getClasspath() {
return classpath;
}
public void setClasspath(FileCollection configuration) {
this.classpath = configuration;
}
public MinimalJavadocOptions getOptions() {
return options;
}
public void setOptions(MinimalJavadocOptions options) {
this.options = options;
}
public boolean isFailOnError() {
return failOnError;
}
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
public File getOptionsFile() {
return new File(getTemporaryDir(), "javadoc.options");
}
public String getExecutable() {
return executable;
}
public void setExecutable(String executable) {
this.executable = executable;
}
private Aggregator aggregator;
public void aggregator(Closure closure) {
if ( aggregator == null ) {
aggregator = new Aggregator(this);
}
ConfigureUtil.configure(closure, aggregator);
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.build.gradle.upload;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import org.apache.maven.artifact.ant.Authentication;
import org.apache.maven.artifact.ant.RemoteRepository;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
/**
* Responsible for locating and injecting authentication information into the JBoss Nexus repository config for upload
* which it does, based on set up in
*
* @author Steve Ebersole
*/
public class Authenticator extends DefaultTask {
private Set<RemoteRepository> nexusRepositories = new HashSet<RemoteRepository>();
void addRepository(RemoteRepository remoteRepository) {
nexusRepositories.add( remoteRepository );
}
@TaskAction
public void configureNexusAuthentication() {
// See if we have username/password...
Authentication authentication = locateAuthenticationDetails();
if ( authentication == null ) {
if ( ! nexusRepositories.isEmpty() ) {
getLogger().warn( "Unable to locate JBoss Nexus username/password; upload will most likely fail" );
}
return;
}
for ( RemoteRepository remoteRepository : nexusRepositories ) {
remoteRepository.addAuthentication( authentication );
}
}
public static final String ALT_PROP_FILE_NAME = "jboss-nexus.properties";
public static final String USER = "JBOSS_NEXUS_USERNAME";
public static final String PASS = "JBOSS_NEXUS_PASSWORD";
private Authentication locateAuthenticationDetails() {
String username = (String) getProject().getProperties().get( USER );
String password = (String) getProject().getProperties().get( PASS );
if ( username != null && password != null ) {
return newAuthentication( username, password );
}
File alternateFile = new File( new File( System.getProperty( "user.home" ), ".gradle" ), ALT_PROP_FILE_NAME );
Properties alternateProperties = new Properties();
// in case one or the other were specified...
if ( username != null ) {
alternateProperties.put( USER, username );
}
if ( password != null ) {
alternateProperties.put( PASS, password );
}
try {
FileInputStream fis = new FileInputStream( alternateFile );
try {
alternateProperties.load( fis );
}
catch ( IOException e ) {
getLogger().debug( "Unable to load alternate JBoss Nexus properties file", e );
}
finally {
try {
fis.close();
}
catch ( IOException ignore ) {
}
}
}
catch ( FileNotFoundException e ) {
getLogger().debug( "Unable to locate alternate JBoss Nexus properties file" );
}
username = alternateProperties.getProperty( USER );
password = alternateProperties.getProperty( PASS );
if ( username != null && password != null ) {
return newAuthentication( username, password );
}
return null;
}
private Authentication newAuthentication(String username, String password) {
Authentication authentication = new Authentication();
authentication.setUserName( username );
authentication.setPassword( password );
return authentication;
}
}

View File

@ -0,0 +1,68 @@
/*
* 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.build.gradle.upload;
import org.apache.maven.artifact.ant.RemoteRepository;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.maven.MavenDeployer;
import org.gradle.api.tasks.Upload;
/**
* Plugin to manage authentication
*
* @author Steve Ebersole
*/
public class UploadManager implements Plugin<Project> {
@Override
public void apply(Project project) {
final Authenticator authenticator = project.getTasks().add( "nexusAuthHandler", Authenticator.class );
project.getTasks().withType( Upload.class ).allTasks(
new Action<Upload>() {
@Override
public void execute(final Upload uploadTask) {
uploadTask.getRepositories().withType( MavenDeployer.class ).allObjects(
new Action<MavenDeployer>() {
public void execute(MavenDeployer deployer) {
RemoteRepository repository = deployer.getRepository();
if ( repository != null ) {
authenticator.addRepository( repository );
uploadTask.getDependsOn().add( authenticator );
}
repository = deployer.getSnapshotRepository();
if ( repository != null ) {
authenticator.addRepository( repository );
uploadTask.getDependsOn().add( authenticator );
}
}
}
);
}
}
);
}
}

View File

@ -1,175 +0,0 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2009, 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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-parent</artifactId>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jbosscache</artifactId>
<packaging>jar</packaging>
<name>Hibernate JBossCache Integration</name>
<description>Integration of Hibernate with JBossCache 3.x (though 2.x sould work as well)</description>
<dependencies>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>hibernate-core</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>org.jboss.cache</groupId>
<artifactId>jbosscache-core</artifactId>
<version>3.2.1.GA</version>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>${groupId}</groupId>
<artifactId>hibernate-testing</artifactId>
<version>${version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.2</version>
<scope>test</scope>
</dependency>
<!-- this is optional on core :( and needed for testing -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<filtering>false</filtering>
<directory>src/test/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</testResource>
<testResource>
<filtering>true</filtering>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<!-- Skip a long-running test of a prototype class -->
<exclude>**/ClusteredConcurrentTimestampRegionTestCase.java</exclude>
</excludes>
<systemProperties>
<property>
<name>hibernate.test.validatefailureexpected</name>
<value>true</value>
</property>
<property>
<name>jgroups.bind_addr</name>
<value>${jgroups.bind_addr}</value>
</property>
<!-- There are problems with multicast and IPv6 on some
OS/JDK combos, so we tell Java to use IPv4. If you
have problems with multicast when running the tests
you can try setting this to 'false', although typically
that won't be helpful.
-->
<property>
<name>java.net.preferIPv4Stack</name>
<value>true</value>
</property>
<!-- Tell JGroups to only wait a short time for PING
responses before determining coordinator. Speeds cluster
formation during integration tests. (This is too
low a value for a real system; only use for tests.)
-->
<property>
<name>jgroups.ping.timeout</name>
<value>500</value>
</property>
<!-- Tell JGroups to only require one PING response
before determining coordinator. Speeds cluster
formation during integration tests. (This is too
low a value for a real system; only use for tests.)
-->
<property>
<name>jgroups.ping.num_initial_members</name>
<value>1</value>
</property>
<!-- Disable the JGroups message bundling feature
to speed tests and avoid FLUSH issue -->
<property>
<name>jgroups.udp.enable_bundling</name>
<value>false</value>
</property>
</systemProperties>
<skipExec>${skipUnitTests}</skipExec>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<skipUnitTests>true</skipUnitTests>
<!--
Following is the default jgroups mcast address. If you find the testsuite runs very slowly, there
may be problems with multicast on the interface JGroups uses by default on your machine. You can
try to resolve setting 'jgroups.bind_addr' as a system-property to the jvm launching maven and
setting the value to an interface where you know multicast works
-->
<jgroups.bind_addr>127.0.0.1</jgroups.bind_addr>
</properties>
<profiles>
<profile>
<id>test</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<skipUnitTests>false</skipUnitTests>
</properties>
</profile>
</profiles>
</project>

View File

@ -1,580 +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.jbc;
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;
import javax.transaction.TransactionManager;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.Region;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cache.jbc.util.NonLockingDataVersion;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
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.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;
/**
* General support for writing {@link Region} implementations for JBoss Cache
* 2.x.
*
* @author Steve Ebersole
*/
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);
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);
}
protected abstract Fqn<String> createRegionFqn(String regionName, String regionPrefix);
protected void activateLocalClusterNode() {
// Regions can get instantiated in the course of normal work (e.g.
// a named query region will be created the first time the query is
// executed), so suspend any ongoing tx
Transaction tx = suspend();
try {
Configuration cfg = jbcCache.getConfiguration();
if (cfg.isUseRegionBasedMarshalling()) {
org.jboss.cache.Region jbcRegion = jbcCache.getRegion(regionFqn, true);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = getClass().getClassLoader();
}
jbcRegion.registerContextClassLoader(classLoader);
if ( !jbcRegion.isActive() ) {
jbcRegion.activate();
}
}
// // If we are using replication, we may remove the root node
// // and then need to re-add it. In that case, the fact
// // that it is resident will not replicate, so use a listener
// // to set it as resident
// if (CacheHelper.isClusteredReplication(cfg.getCacheMode())
// || CacheHelper.isClusteredInvalidation(cfg.getCacheMode())) {
// listener = new RegionRootListener();
// jbcCache.addCacheListener(listener);
// }
regionRoot = jbcCache.getRoot().getChild( regionFqn );
if (regionRoot == null || !regionRoot.isValid()) {
// Establish the region root node with a non-locking data version
DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE : null;
regionRoot = CacheHelper.addNode(jbcCache, regionFqn, true, true, version);
}
else if (optimistic && regionRoot instanceof NodeSPI) {
// FIXME Hacky workaround to JBCACHE-1202
if ( !( ( ( NodeSPI ) regionRoot ).getVersion() instanceof NonLockingDataVersion ) ) {
((NodeSPI) regionRoot).setVersion(NonLockingDataVersion.INSTANCE);
}
}
if (!regionRoot.isResident()) {
regionRoot.setResident(true);
}
establishInternalNodes();
}
catch (Exception e) {
throw new CacheException(e.getMessage(), e);
}
finally {
resume(tx);
}
}
private void establishRegionRootNode()
{
synchronized (regionRootMutex) {
// If we've been blocking for the mutex, perhaps another
// thread has already reestablished the root.
// In case the node was reestablised via replication, confirm it's
// marked "resident" (a status which doesn't replicate)
if (regionRoot != null && regionRoot.isValid()) {
return;
}
// 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;
}
// The rest only matters for optimistic locking, where we
// need to establish the proper data version on the region root
// Don't hold a transactional lock for this
Transaction tx = suspend();
Node newRoot = null;
try {
// Make sure the root node for the region exists and
// has a DataVersion that never complains
newRoot = jbcCache.getRoot().getChild( regionFqn );
if (newRoot == null || !newRoot.isValid()) {
// Establish the region root node with a non-locking data version
DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE : null;
newRoot = CacheHelper.addNode(jbcCache, regionFqn, true, true, version);
}
else if (newRoot instanceof NodeSPI) {
// FIXME Hacky workaround to JBCACHE-1202
if ( !( ( ( NodeSPI ) newRoot ).getVersion() instanceof NonLockingDataVersion ) ) {
((NodeSPI) newRoot).setVersion(NonLockingDataVersion.INSTANCE);
}
}
// Never evict this node
newRoot.setResident(true);
establishInternalNodes();
}
finally {
resume(tx);
regionRoot = newRoot;
}
}
}
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;
}
public Cache getCacheInstance() {
return jbcCache;
}
public Fqn getRegionFqn() {
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
* ensuring that the root node is marked as resident. Suspends any
* transaction while doing this to ensure no transactional locks are held
* on the region root.
*
* TODO remove this once JBCACHE-1250 is resolved.
*/
public void ensureRegionRootExists() {
if (regionRoot == null || !regionRoot.isValid())
establishRegionRootNode();
// Fix up the resident flag
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 {
// NOTE : this is being used from the process of shutting down a
// SessionFactory. Specific things to consider:
// (1) this clearing of the region should not propagate to
// other nodes on the cluster (if any); this is the
// cache-mode-local option bit...
// (2) really just trying a best effort to cleanup after
// ourselves; lock failures, etc are not critical here;
// this is the fail-silently option bit...
Option option = new Option();
option.setCacheModeLocal(true);
option.setFailSilently(true);
if (optimistic) {
option.setDataVersion(NonLockingDataVersion.INSTANCE);
}
jbcCache.getInvocationContext().setOptionOverrides(option);
jbcCache.removeNode(regionFqn);
deactivateLocalNode();
} catch (Exception e) {
throw new CacheException(e);
}
finally {
jbcCache.removeCacheListener(this);
}
}
protected void deactivateLocalNode() {
org.jboss.cache.Region jbcRegion = jbcCache.getRegion(regionFqn, false);
if (jbcRegion != null && jbcRegion.isActive()) {
jbcRegion.deactivate();
jbcRegion.unregisterContextClassLoader();
}
}
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() {
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() {
return -1;
}
public Map toMap() {
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();
}
}
public long nextTimestamp() {
return System.currentTimeMillis() / 100;
}
public int getTimeout() {
return 600; // 60 seconds
}
/**
* Performs a JBoss Cache <code>get(Fqn, Object)</code> after first
* {@link #suspend suspending any ongoing transaction}. Wraps any exception
* in a {@link CacheException}. Ensures any ongoing transaction is resumed.
*
* @param key The key of the item to get
* @param opt any option to add to the get invocation. May be <code>null</code>
* @param suppressTimeout should any TimeoutException be suppressed?
* @return The retrieved object
* @throws CacheException issue managing transaction or talking to cache
*/
protected Object suspendAndGet(Object key, Option opt, boolean suppressTimeout) throws CacheException {
Transaction tx = suspend();
try {
CacheHelper.setInvocationOption(getCacheInstance(), opt);
if (suppressTimeout)
return CacheHelper.getAllowingTimeout(getCacheInstance(), getRegionFqn(), key);
else
return CacheHelper.get(getCacheInstance(), getRegionFqn(), key);
} finally {
resume(tx);
}
}
/**
* Tell the TransactionManager to suspend any ongoing transaction.
*
* @return the transaction that was suspended, or <code>null</code> if
* there wasn't one
*/
public Transaction suspend() {
Transaction tx = null;
try {
if (transactionManager != null) {
tx = transactionManager.suspend();
}
} catch (SystemException se) {
throw new CacheException("Could not suspend transaction", se);
}
return tx;
}
/**
* Tell the TransactionManager to resume the given transaction
*
* @param tx
* the transaction to suspend. May be <code>null</code>.
*/
public void resume(Transaction tx) {
try {
if (tx != null)
transactionManager.resume(tx);
} catch (Exception e) {
throw new CacheException("Could not resume transaction", e);
}
}
/**
* Get an Option with a {@link Option#getDataVersion() data version}
* of {@link NonLockingDataVersion}. The data version will not be
* set if the cache is not configured for optimistic locking.
*
* @param allowNullReturn If <code>true</code>, return <code>null</code>
* if the cache is not using optimistic locking.
* If <code>false</code>, return a default
* {@link Option}.
*
* @return the Option, or <code>null</code>.
*/
protected Option getNonLockingDataVersionOption(boolean allowNullReturn) {
return optimistic ? NonLockingDataVersion.getInvocationOption()
: (allowNullReturn) ? null : new Option();
}
public static Fqn<String> getTypeFirstRegionFqn(String regionName, String regionPrefix, String regionType) {
Fqn<String> base = Fqn.fromString(regionType);
Fqn<String> added = Fqn.fromString(escapeRegionName(regionName, regionPrefix));
return new Fqn<String>(base, added);
}
public static Fqn<String> getTypeLastRegionFqn(String regionName, String regionPrefix, String regionType) {
Fqn<String> base = Fqn.fromString(escapeRegionName(regionName, regionPrefix));
return new Fqn<String>(base, regionType);
}
public static String escapeRegionName(String regionName, String regionPrefix) {
String escaped = null;
int idx = -1;
if (regionPrefix != null) {
idx = regionName.indexOf(regionPrefix);
}
if (idx > -1) {
int regionEnd = idx + regionPrefix.length();
String prefix = regionName.substring(0, regionEnd);
String suffix = regionName.substring(regionEnd);
suffix = suffix.replace('.', '/');
escaped = prefix + suffix;
} else {
escaped = regionName.replace('.', '/');
if (regionPrefix != null && regionPrefix.length() > 0) {
escaped = regionPrefix + "/" + escaped;
}
}
return escaped;
}
@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

@ -1,91 +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.jbc;
import java.util.Properties;
import org.hibernate.cache.CacheException;
import org.hibernate.cfg.Settings;
import org.jboss.cache.Cache;
/**
* Acts as a buffer from how instances of {@link Cache} are built/obtained.
*
* @author Steve Ebersole
*/
public interface CacheInstanceManager {
/**
* Retrieve a handle to the {@link Cache} instance to be used for storing
* entity data.
*
* @return The entity data cache instance.
*/
public Cache getEntityCacheInstance();
/**
* Retrieve a handle to the {@link Cache} instance to be used for storing
* collection data.
*
* @return The collection data cache instance.
*/
public Cache getCollectionCacheInstance();
/**
* Retrieve a handle to the {@link Cache} instance to be used for storing
* query results.
*
* @return The query result cache instance.
*/
public Cache getQueryCacheInstance();
/**
* Retrieve a handle to the {@link Cache} instance to be used for storing
* timestamps.
*
* @return The timestamps cache instance.
*/
public Cache getTimestampsCacheInstance();
/**
* Lifecycle callback to perform any necessary initialization of the
* CacheInstanceManager. Called exactly once during the construction of a
* {@link org.hibernate.impl.SessionFactoryImpl}.
*
* @param settings
* The settings in effect.
* @param properties
* The defined cfg properties
* @throws CacheException
* Indicates problems starting the L2 cache impl; considered as
* a sign to stop {@link org.hibernate.SessionFactory} building.
*/
public void start(Settings settings, Properties properties) throws CacheException;
/**
* Lifecycle callback to perform any necessary cleanup of the underlying
* CacheInstanceManager. Called exactly once during
* {@link org.hibernate.SessionFactory#close}.
*/
public void stop();
}

View File

@ -1,164 +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.jbc;
import java.util.Properties;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.TimestampsRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.jbc.builder.JndiSharedCacheInstanceManager;
import org.hibernate.cache.jbc.builder.SharedCacheInstanceManager;
import org.hibernate.cache.jbc.collection.CollectionRegionImpl;
import org.hibernate.cache.jbc.entity.EntityRegionImpl;
import org.hibernate.cache.jbc.query.QueryResultsRegionImpl;
import org.hibernate.cache.jbc.timestamp.TimestampsRegionImpl;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.Settings;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.jboss.cache.DefaultCacheFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link RegionFactory} that uses one or more JBoss Cache instances for
* caching entities, collections, queries and timestamps. How the factory
* obtains a reference to the needed JBoss Cache instance(s) is determined
* by the injected {@link CacheInstanceManager}.
* <p>
* By default uses {@link SharedCacheInstanceManager} as its
* {@link #getCacheInstanceManager() CacheInstanceManager}.
* Basically, this uses a single shared JBoss Cache for entities, collections,
* queries and timestamps. The JBoss Cache instance is created by the
* JBC {@link DefaultCacheFactory} using the resource identified by the
* {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
* configuration property.
* </p>
* <p>
* Also exposes an overloaded constructor that allows injection of different
* <code>CacheInstanceManager</code> implementations.
* </p>
*
* @deprecated Favor Infinispan integration; see HHH-5489 for details.
*
* @author Steve Ebersole
* @author Brian Stansberry
*/
@Deprecated
public class JBossCacheRegionFactory implements RegionFactory {
private static final Logger log = LoggerFactory.getLogger( JBossCacheRegionFactory.class );
private CacheInstanceManager cacheInstanceManager;
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public JBossCacheRegionFactory(Properties props) {
this();
}
/**
* Create a new JBossCacheRegionFactory.
*/
public JBossCacheRegionFactory() {
log.warn( "Integration with JBossCache is deprecated in favor of Infinispan" );
}
/**
* Create a new JBossCacheRegionFactory that uses the provided
* {@link CacheInstanceManager}.
*
* @param cacheInstanceManager The contract for how we get JBC cache instances.
*/
public JBossCacheRegionFactory(CacheInstanceManager cacheInstanceManager) {
this.cacheInstanceManager = cacheInstanceManager;
log.warn( "Integration with JBossCache is deprecated in favor of Infinispan" );
}
public CacheInstanceManager getCacheInstanceManager() {
return cacheInstanceManager;
}
public void start(Settings settings, Properties properties) throws CacheException {
if (cacheInstanceManager == null) {
cacheInstanceManager = new SharedCacheInstanceManager();
}
cacheInstanceManager.start(settings, properties);
}
public void stop() {
if (cacheInstanceManager != null) {
cacheInstanceManager.stop();
}
}
public boolean isMinimalPutsEnabledByDefault() {
return true;
}
public AccessType getDefaultAccessType() {
return AccessType.TRANSACTIONAL;
}
public long nextTimestamp() {
return System.currentTimeMillis() / 100;
}
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
throws CacheException {
return new EntityRegionImpl(cacheInstanceManager.getEntityCacheInstance(), regionName,
getRegionPrefix(properties), metadata);
}
public CollectionRegion buildCollectionRegion(String regionName, Properties properties,
CacheDataDescription metadata) throws CacheException {
return new CollectionRegionImpl(cacheInstanceManager.getCollectionCacheInstance(), regionName,
getRegionPrefix(properties), metadata);
}
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
return new QueryResultsRegionImpl(cacheInstanceManager.getQueryCacheInstance(), regionName,
getRegionPrefix(properties), properties);
}
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
return new TimestampsRegionImpl(cacheInstanceManager.getTimestampsCacheInstance(), regionName,
getRegionPrefix(properties), properties);
}
public static String getRegionPrefix(Properties properties) {
return ConfigurationHelper.getString(Environment.CACHE_REGION_PREFIX, properties, null);
}
}

View File

@ -1,74 +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.jbc;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.jbc.builder.JndiMultiplexingCacheInstanceManager;
/**
* {@link JBossCacheRegionFactory} that uses
* {@link JndiMultiplexingCacheInstanceManager} as its
* {@link #getCacheInstanceManager() CacheInstanceManager}.
* <p>
* Supports separate JBoss Cache instances for entity, collection, query
* and timestamp caching, with the expectation that a single multiplexed JGroups
* resource (i.e. a multiplexed channel or a shared transport channel) will be
* shared between the caches. JBoss Cache instances are created from a factory.
* </p>
* <p>
* This version finds the factory in JNDI. See
* {@link JndiMultiplexingCacheInstanceManager} for configuration details.
* </p>
*
* @deprecated Favor Infinispan integration; see HHH-5489 for details.
*
* @author Brian Stansberry
* @version $Revision$
*/
@Deprecated
public class JndiMultiplexedJBossCacheRegionFactory extends JBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public JndiMultiplexedJBossCacheRegionFactory(Properties props) {
this();
}
/**
* Create a new MultiplexedJBossCacheRegionFactory.
*
*/
public JndiMultiplexedJBossCacheRegionFactory() {
super(new JndiMultiplexingCacheInstanceManager());
}
}

View File

@ -1,67 +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.jbc;
import java.util.Properties;
import org.hibernate.cache.jbc.builder.JndiSharedCacheInstanceManager;
/**
* {@link JBossCacheRegionFactory} that uses
* {@link JndiSharedCacheInstanceManager} as its
* {@link #getCacheInstanceManager() CacheInstanceManager}.
* <p>
* Basically, uses a single shared JBoss Cache for entities, collections,
* queries and timestamps. The JBoss Cache instance is found in JNDI
* using the value of the {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
* configuration property as the name to look up.
* </p>
*
* @deprecated Favor Infinispan integration; see HHH-5489 for details.
*
* @author Brian Stansberry
* @version $Revision$
*/
@Deprecated
public class JndiSharedJBossCacheRegionFactory extends JBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public JndiSharedJBossCacheRegionFactory(Properties props) {
this();
}
/**
* Create a new MultiplexedJBossCacheRegionFactory.
*
*/
public JndiSharedJBossCacheRegionFactory() {
super(new JndiSharedCacheInstanceManager());
}
}

View File

@ -1,71 +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.jbc;
import java.util.Properties;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
/**
* {@link JBossCacheRegionFactory} that uses
* {@link MultiplexingCacheInstanceManager} as its
* {@link #getCacheInstanceManager() CacheInstanceManager}.
* <p>
* Supports separate JBoss Cache instances for entity, collection, query
* and timestamp caching, with the expectation that a single JGroups resource
* (i.e. a multiplexed channel or a shared transport channel) will be shared
* between the caches. JBoss Cache instances are created from a factory.
* </p>
* <p>
* This version instantiates the factory itself. See
* {@link MultiplexingCacheInstanceManager} for configuration details.
* </p>
*
* @deprecated Favor Infinispan integration; see HHH-5489 for details.
*
* @author Brian Stansberry
* @version $Revision$
*/
@Deprecated
public class MultiplexedJBossCacheRegionFactory extends JBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public MultiplexedJBossCacheRegionFactory(Properties props) {
this();
}
/**
* Create a new MultiplexedJBossCacheRegionFactory.
*
*/
public MultiplexedJBossCacheRegionFactory() {
super(new MultiplexingCacheInstanceManager());
}
}

View File

@ -1,72 +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.jbc;
import java.util.Properties;
import org.hibernate.cache.jbc.builder.JndiSharedCacheInstanceManager;
import org.hibernate.cache.jbc.builder.SharedCacheInstanceManager;
import org.jboss.cache.DefaultCacheFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link JBossCacheRegionFactory} that uses
* {@link SharedCacheInstanceManager} as its
* {@link #getCacheInstanceManager() CacheInstanceManager}.
* <p>
* Basically, uses a single shared JBoss Cache for entities, collections,
* queries and timestamps. The JBoss Cache instance created by the
* JBC {@link DefaultCacheFactory} using the resource identified by the
* {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
* configuration property.
* </p>
*
* @deprecated Favor Infinispan integration; see HHH-5489 for details.
*
* @author Brian Stansberry
* @version $Revision$
*/
@Deprecated
public class SharedJBossCacheRegionFactory extends JBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public SharedJBossCacheRegionFactory(Properties props) {
this();
}
/**
* Create a new MultiplexedJBossCacheRegionFactory.
*
*/
public SharedJBossCacheRegionFactory() {
super(new SharedCacheInstanceManager());
}
}

View File

@ -1,60 +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.jbc;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.TransactionalDataRegion;
import org.jboss.cache.Cache;
/**
* {@inheritDoc}
*
* @author Steve Ebersole
*/
public abstract class TransactionalDataRegionAdapter extends BasicRegionAdapter implements TransactionalDataRegion {
protected final CacheDataDescription metadata;
public TransactionalDataRegionAdapter(Cache jbcCache, String regionName, String regionPrefix,
CacheDataDescription metadata) {
super(jbcCache, regionName, regionPrefix);
this.metadata = metadata;
}
/**
* Here, for JBossCache, we consider the cache to be transaction aware if
* the underlying cache instance has a reference to the transaction manager.
*/
public boolean isTransactionAware() {
return transactionManager != null;
}
/**
* {@inheritDoc}
*/
public CacheDataDescription getCacheDataDescription() {
return metadata;
}
}

View File

@ -1,212 +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.jbc.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.jbc.TransactionalDataRegionAdapter;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cache.jbc.util.DataVersionAdapter;
import org.hibernate.cache.jbc.util.NonLockingDataVersion;
import org.jboss.cache.config.Option;
/**
* Defines the strategy for transactional access to entity or collection data in
* an optimistic-locking JBoss Cache using its 2.x APIs.
* <p>
* The intent of this class is to encapsulate common code and serve as a
* delegate for {@link EntityRegionAccessStrategy} and
* {@link CollectionRegionAccessStrategy} implementations.
* </p>
*
* @author Brian Stansberry
* @version $Revision: 1 $
*/
public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDelegate {
protected final CacheDataDescription dataDescription;
public OptimisticTransactionalAccessDelegate(TransactionalDataRegionAdapter region, PutFromLoadValidator validator) {
super(region, validator);
this.dataDescription = region.getCacheDataDescription();
}
/**
* Overrides the
* {@link TransactionalAccessDelegate#evict(Object) superclass} by adding a
* {@link NonLockingDataVersion} to the invocation.
*/
@Override
public void evict(Object key) throws CacheException {
if (!putValidator.invalidateKey(key)) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for key " + key + " from region " + region.getName());
}
region.ensureRegionRootExists();
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.remove(cache, regionFqn, key, opt);
}
@Override
public void evictAll() throws CacheException
{
if (!putValidator.invalidateRegion()) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for region " + region.getName());
}
Transaction tx = region.suspend();
try {
region.ensureRegionRootExists();
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.sendEvictAllNotification(cache, regionFqn, region.getMemberId(), opt);
}
finally {
region.resume(tx);
}
}
/**
* Overrides the
* {@link TransactionalAccessDelegate#insert(Object, Object, Object) superclass}
* by adding a {@link DataVersion} to the invocation.
*/
@Override
public boolean insert(Object key, Object value, Object version) throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
Option opt = getDataVersionOption(version, null);
if (this.invalidation) {
opt.setCacheModeLocal(true);
}
CacheHelper.put(cache, regionFqn, key, value, opt);
return true;
}
@Override
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if (!region.checkValid())
return false;
if (!putValidator.acquirePutFromLoadLock(key))
return false;
try {
region.ensureRegionRootExists();
// We ignore minimalPutOverride. JBossCache putForExternalRead is
// already about as minimal as we can get; it will promptly return
// if it discovers that the node we want to write to already exists
Option opt = getDataVersionOption(version, version);
return CacheHelper.putForExternalRead(cache, regionFqn, key, value, opt);
}
finally {
putValidator.releasePutFromLoadLock(key);
}
}
@Override
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
if (!region.checkValid())
return false;
if (!putValidator.acquirePutFromLoadLock(key))
return false;
try {
region.ensureRegionRootExists();
Option opt = getDataVersionOption(version, version);
return CacheHelper.putForExternalRead(cache, regionFqn, key, value, opt);
}
finally {
putValidator.releasePutFromLoadLock(key);
}
}
@Override
public void remove(Object key) throws CacheException {
if (!putValidator.invalidateKey(key)) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for key " + key + " from region " + region.getName());
}
// 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();
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.remove(cache, regionFqn, key, opt);
}
@Override
public void removeAll() throws CacheException {
if (!putValidator.invalidateRegion()) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for region " + region.getName());
}
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);
CacheHelper.put(cache, regionFqn, key, value, opt);
return true;
}
@SuppressWarnings("deprecation")
private Option getDataVersionOption(Object currentVersion, Object previousVersion) {
org.jboss.cache.optimistic.DataVersion dv = (dataDescription != null && dataDescription.isVersioned()) ? new DataVersionAdapter(
currentVersion, previousVersion, dataDescription.getVersionComparator(), dataDescription.toString())
: NonLockingDataVersion.INSTANCE;
Option opt = new Option();
opt.setDataVersion(dv);
return opt;
}
}

View File

@ -1,744 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, 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 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.jbc.access;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.hibernate.cache.CacheException;
/**
* Encapsulates logic to allow a {@link TransactionalAccessDelegate} to determine
* whether a {@link TransactionalAccessDelegate#putFromLoad(Object, Object, long, Object, boolean)
* call should be allowed to update the cache. A <code>putFromLoad</code> has
* the potential to store stale data, since the data may have been removed from the
* database and the cache between the time when the data was read from the database
* and the actual call to <code>putFromLoad</code>.
* <p>
* The expected usage of this class by a thread that read the cache and did
* not find data is:
*
* <ol>
* <li> Call {@link #registerPendingPut(Object)}</li>
* <li> Read the database</li>
* <li> Call {@link #acquirePutFromLoadLock(Object)}
* <li> if above returns <code>false</code>, the thread should not cache the data;
* only if above returns <code>true</code>, put data in the cache and...</li>
* <li> then call {@link #releasePutFromLoadLock(Object)}</li>
* </ol>
* </p>
*
* <p>
* The expected usage by a thread that is taking an action such that any pending
* <code>putFromLoad</code> may have stale data and should not cache it is to either
* call
*
* <ul>
* <li> {@link #invalidateKey(Object)} (for a single key invalidation)</li>
* <li>or {@link #invalidateRegion()} (for a general invalidation all pending puts)</li>
* </ul>
* </p>
*
* <p>
* This class also supports the concept of "naked puts", which are calls to
* {@link #acquirePutFromLoadLock(Object)} without a preceding {@link #registerPendingPut(Object)}
* call.
* </p>
*
* @author Brian Stansberry
*
* @version $Revision: $
*/
public class PutFromLoadValidator {
/**
* Period in ms after a removal during which a call to
* {@link #acquirePutFromLoadLock(Object)} that hasn't been
* {@link #registerPendingPut(Object) pre-registered} (aka a "naked put")
* will return false.
*/
public static final long NAKED_PUT_INVALIDATION_PERIOD = 20 * 1000;
/** Period (in ms) after which a pending put is placed in the over-age queue */
private static final long PENDING_PUT_OVERAGE_PERIOD = 5 * 1000;
/** Period (in ms) before which we stop trying to clean out pending puts */
private static final long PENDING_PUT_RECENT_PERIOD = 2 * 1000;
/**
* Period (in ms) after which a pending put is never expected to come in
* and should be cleaned
*/
private static final long MAX_PENDING_PUT_DELAY = 2 * 60 * 1000;
/**
* Used to determine whether the owner of a pending put is a thread or a
* transaction
*/
private final TransactionManager transactionManager;
private final long nakedPutInvalidationPeriod;
private final long pendingPutOveragePeriod;
private final long pendingPutRecentPeriod;
private final long maxPendingPutDelay;
/**
* Registry of expected, future, isPutValid calls. If a key+owner is
* registered in this map, it is not a "naked put" and is allowed to
* proceed.
*/
private final ConcurrentMap<Object, PendingPutMap> pendingPuts = new ConcurrentHashMap<Object, PendingPutMap>();
/**
* List of pending puts. Used to ensure we don't leak memory via the
* pendingPuts map
*/
private final List<WeakReference<PendingPut>> pendingQueue = new LinkedList<WeakReference<PendingPut>>();
/**
* Separate list of pending puts that haven't been resolved within
* PENDING_PUT_OVERAGE_PERIOD. Used to ensure we don't leak memory via the
* pendingPuts map. Tracked separately from more recent pending puts for
* efficiency reasons.
*/
private final List<WeakReference<PendingPut>> overagePendingQueue = new LinkedList<WeakReference<PendingPut>>();
/** Lock controlling access to pending put queues */
private final Lock pendingLock = new ReentrantLock();
private final ConcurrentMap<Object, Long> recentRemovals = new ConcurrentHashMap<Object, Long>();
/**
* List of recent removals. Used to ensure we don't leak memory via the
* recentRemovals map
*/
private final List<RecentRemoval> removalsQueue = new LinkedList<RecentRemoval>();
/**
* The time when the first element in removalsQueue will expire. No reason
* to do housekeeping on the queue before this time.
*/
private volatile long earliestRemovalTimestamp;
/** Lock controlling access to removalsQueue */
private final Lock removalsLock = new ReentrantLock();
/**
* The time of the last call to regionRemoved(), plus
* NAKED_PUT_INVALIDATION_PERIOD. All naked puts will be rejected until the
* current time is greater than this value.
*/
private volatile long invalidationTimestamp;
/**
* Creates a new PutFromLoadValidator.
*
* @param transactionManager
* transaction manager to use to associate changes with a
* transaction; may be <code>null</code>
*/
public PutFromLoadValidator(TransactionManager transactionManager) {
this(transactionManager, NAKED_PUT_INVALIDATION_PERIOD,
PENDING_PUT_OVERAGE_PERIOD, PENDING_PUT_RECENT_PERIOD,
MAX_PENDING_PUT_DELAY);
}
/**
* Constructor variant for use by unit tests; allows control of various
* timeouts by the test.
*/
protected PutFromLoadValidator(TransactionManager transactionManager,
long nakedPutInvalidationPeriod, long pendingPutOveragePeriod,
long pendingPutRecentPeriod, long maxPendingPutDelay) {
this.transactionManager = transactionManager;
this.nakedPutInvalidationPeriod = nakedPutInvalidationPeriod;
this.pendingPutOveragePeriod = pendingPutOveragePeriod;
this.pendingPutRecentPeriod = pendingPutRecentPeriod;
this.maxPendingPutDelay = maxPendingPutDelay;
}
// ----------------------------------------------------------------- Public
/**
* Acquire a lock giving the calling thread the right to put data in the
* cache for the given key.
* <p>
* <strong>NOTE:</strong> A call to this method that returns <code>true</code>
* should always be matched with a call to {@link #releasePutFromLoadLock(Object)}.
* </p>
*
* @param key the key
*
* @return <code>true</code> if the lock is acquired and the cache put
* can proceed; <code>false</code> if the data should not be cached
*/
public boolean acquirePutFromLoadLock(Object key) {
boolean valid = false;
boolean locked = false;
long now = System.currentTimeMillis();
// Important: Do cleanup before we acquire any locks so we
// don't deadlock with invalidateRegion
cleanOutdatedPendingPuts(now, true);
try {
PendingPutMap pending = pendingPuts.get(key);
if (pending != null) {
locked = pending.acquireLock(100, TimeUnit.MILLISECONDS);
if (locked) {
try {
PendingPut toCancel = pending.remove(getOwnerForPut());
if (toCancel != null) {
valid = !toCancel.completed;
toCancel.completed = true;
}
}
finally {
if (!valid) {
pending.releaseLock();
locked = false;
}
}
}
}
else {
// Key wasn't in pendingPuts, so either this is a "naked put"
// or regionRemoved has been called. Check if we can proceed
if (now > invalidationTimestamp) {
Long removedTime = recentRemovals.get(key);
if (removedTime == null || now > removedTime.longValue()) {
// It's legal to proceed. But we have to record this key
// in pendingPuts so releasePutFromLoadLock can find it.
// To do this we basically simulate a normal "register
// then acquire lock" pattern
registerPendingPut(key);
locked = acquirePutFromLoadLock(key);
valid = locked;
}
}
}
}
catch (Throwable t) {
valid = false;
if (locked) {
PendingPutMap toRelease = pendingPuts.get(key);
if (toRelease != null) {
toRelease.releaseLock();
}
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
else if (t instanceof Error) {
throw (Error) t;
}
else {
throw new RuntimeException(t);
}
}
return valid;
}
/**
* Releases the lock previously obtained by a call to
* {@link #acquirePutFromLoadLock(Object)} that returned <code>true</code>.
*
* @param key the key
*/
public void releasePutFromLoadLock(Object key) {
PendingPutMap pending = pendingPuts.get(key);
if (pending != null) {
if (pending.size() == 0) {
pendingPuts.remove(key);
}
pending.releaseLock();
}
}
/**
* Invalidates any {@link #registerPendingPut(Object) previously registered pending puts}
* ensuring a subsequent call to {@link #acquirePutFromLoadLock(Object)} will
* return <code>false</code>.
* <p>
* This method will block until any concurrent thread that has
* {@link #acquirePutFromLoadLock(Object) acquired the putFromLoad lock} for
* the given key has released the lock. This allows the caller to be certain
* the putFromLoad will not execute after this method returns, possibly
* caching stale data.
* </p>
*
* @param key key identifying data whose pending puts should be invalidated
*
* @return <code>true</code> if the invalidation was successful; <code>false</code>
* if a problem occured (which the caller should treat as an
* exception condition)
*/
public boolean invalidateKey(Object key) {
boolean success = true;
// Invalidate any pending puts
PendingPutMap pending = pendingPuts.get(key);
if (pending != null) {
// This lock should be available very quickly, but we'll be
// very patient waiting for it as callers should treat not
// acquiring it as an exception condition
if (pending.acquireLock(60, TimeUnit.SECONDS)) {
try {
pending.invalidate();
}
finally {
pending.releaseLock();
}
}
else {
success = false;
}
}
// Record when this occurred to invalidate later naked puts
RecentRemoval removal = new RecentRemoval(key,
this.nakedPutInvalidationPeriod);
recentRemovals.put(key, removal.timestamp);
// Don't let recentRemovals map become a memory leak
RecentRemoval toClean = null;
boolean attemptClean = removal.timestamp.longValue() > earliestRemovalTimestamp;
removalsLock.lock();
try {
removalsQueue.add(removal);
if (attemptClean) {
if (removalsQueue.size() > 1) { // we have at least one as we
// just added it
toClean = removalsQueue.remove(0);
}
earliestRemovalTimestamp = removalsQueue.get(0).timestamp
.longValue();
}
} finally {
removalsLock.unlock();
}
if (toClean != null) {
Long cleaned = recentRemovals.get(toClean.key);
if (cleaned != null && cleaned.equals(toClean.timestamp)) {
cleaned = recentRemovals.remove(toClean.key);
if (cleaned != null
&& cleaned.equals(toClean.timestamp) == false) {
// Oops; removed the wrong timestamp; restore it
recentRemovals.putIfAbsent(toClean.key, cleaned);
}
}
}
return success;
}
/**
* Invalidates all {@link #registerPendingPut(Object) previously registered pending puts}
* ensuring a subsequent call to {@link #acquirePutFromLoadLock(Object)} will
* return <code>false</code>.
* <p>
* This method will block until any concurrent thread that has
* {@link #acquirePutFromLoadLock(Object) acquired the putFromLoad lock} for
* the any key has released the lock. This allows the caller to be certain
* the putFromLoad will not execute after this method returns, possibly
* caching stale data.
* </p>
*
* @return <code>true</code> if the invalidation was successful; <code>false</code>
* if a problem occured (which the caller should treat as an
* exception condition)
*/
public boolean invalidateRegion() {
boolean ok = false;
invalidationTimestamp = System.currentTimeMillis()
+ this.nakedPutInvalidationPeriod;
try {
// Acquire the lock for each entry to ensure any ongoing
// work associated with it is completed before we return
for (PendingPutMap entry : pendingPuts.values()) {
if (entry.acquireLock(60, TimeUnit.SECONDS)) {
try {
entry.invalidate();
}
finally {
entry.releaseLock();
}
}
else {
ok = false;
}
}
removalsLock.lock();
try {
recentRemovals.clear();
removalsQueue.clear();
ok = true;
} finally {
removalsLock.unlock();
}
}
catch (Exception e) {
ok = false;
}
finally {
earliestRemovalTimestamp = invalidationTimestamp;
}
return ok;
}
/**
* Notifies this validator that it is expected that a database read followed
* by a subsequent {@link #acquirePutFromLoadLock(Object)} call will occur. The intent
* is this method would be called following a cache miss wherein it is
* expected that a database read plus cache put will occur. Calling this
* method allows the validator to treat the subsequent
* <code>acquirePutFromLoadLock</code> as if the database read occurred when this method
* was invoked. This allows the validator to compare the timestamp of this
* call against the timestamp of subsequent removal notifications. A put
* that occurs without this call preceding it is "naked"; i.e the validator
* must assume the put is not valid if any relevant removal has occurred
* within {@link #NAKED_PUT_INVALIDATION_PERIOD} milliseconds.
*
* @param key key that will be used for subsequent cache put
*/
public void registerPendingPut(Object key) {
PendingPut pendingPut = new PendingPut(key, getOwnerForPut());
PendingPutMap pendingForKey = new PendingPutMap(pendingPut);
for (;;) {
PendingPutMap existing = pendingPuts.putIfAbsent(key,
pendingForKey);
if (existing != null) {
if (existing.acquireLock(10, TimeUnit.SECONDS)) {
try {
existing.put(pendingPut);
PendingPutMap doublecheck = pendingPuts.putIfAbsent(
key, existing);
if (doublecheck == null || doublecheck == existing) {
break;
}
// else we hit a race and need to loop to try again
}
finally {
existing.releaseLock();
}
}
else {
// Can't get the lock; when we come back we'll be a "naked put"
break;
}
} else {
// normal case
break;
}
}
// Guard against memory leaks
preventOutdatedPendingPuts(pendingPut);
}
// -------------------------------------------------------------- Protected
/** Only for use by unit tests; may be removed at any time */
protected int getPendingPutQueueLength() {
pendingLock.lock();
try {
return pendingQueue.size();
} finally {
pendingLock.unlock();
}
}
/** Only for use by unit tests; may be removed at any time */
protected int getOveragePendingPutQueueLength() {
pendingLock.lock();
try {
return overagePendingQueue.size();
} finally {
pendingLock.unlock();
}
}
/** Only for use by unit tests; may be removed at any time */
protected int getRemovalQueueLength() {
removalsLock.lock();
try {
return removalsQueue.size();
} finally {
removalsLock.unlock();
}
}
// ---------------------------------------------------------------- Private
private Object getOwnerForPut() {
Transaction tx = null;
try {
if (transactionManager != null) {
tx = transactionManager.getTransaction();
}
} catch (SystemException se) {
throw new CacheException("Could not obtain transaction", se);
}
return tx == null ? Thread.currentThread() : tx;
}
private void preventOutdatedPendingPuts(PendingPut pendingPut) {
pendingLock.lock();
try {
pendingQueue.add(new WeakReference<PendingPut>(pendingPut));
if (pendingQueue.size() > 1) {
cleanOutdatedPendingPuts(pendingPut.timestamp, false);
}
} finally {
pendingLock.unlock();
}
}
private void cleanOutdatedPendingPuts(long now, boolean lock) {
PendingPut toClean = null;
if (lock) {
pendingLock.lock();
}
try {
// Clean items out of the basic queue
long overaged = now - this.pendingPutOveragePeriod;
long recent = now - this.pendingPutRecentPeriod;
int pos = 0;
while (pendingQueue.size() > pos) {
WeakReference<PendingPut> ref = pendingQueue.get(pos);
PendingPut item = ref.get();
if (item == null || item.completed) {
pendingQueue.remove(pos);
} else if (item.timestamp < overaged) {
// Potential leak; move to the overaged queued
pendingQueue.remove(pos);
overagePendingQueue.add(ref);
} else if (item.timestamp >= recent) {
// Don't waste time on very recent items
break;
} else if (pos > 2) {
// Don't spend too much time getting nowhere
break;
} else {
// Move on to the next item
pos++;
}
}
// Process the overage queue until we find an item to clean
// or an incomplete item that hasn't aged out
long mustCleanTime = now - this.maxPendingPutDelay;
while (overagePendingQueue.size() > 0) {
WeakReference<PendingPut> ref = overagePendingQueue.get(0);
PendingPut item = ref.get();
if (item == null || item.completed) {
overagePendingQueue.remove(0);
} else {
if (item.timestamp < mustCleanTime) {
overagePendingQueue.remove(0);
toClean = item;
}
break;
}
}
} finally {
if (lock) {
pendingLock.unlock();
}
}
// We've found a pendingPut that never happened; clean it up
if (toClean != null) {
PendingPutMap map = pendingPuts.get(toClean.key);
if (map != null) {
if (map.acquireLock(100, TimeUnit.MILLISECONDS)) {
try {
PendingPut cleaned = map.remove(toClean.owner);
if (toClean.equals(cleaned) == false) {
// Oops. Restore it.
map.put(cleaned);
} else if (map.size() == 0) {
pendingPuts.remove(toClean.key);
}
}
finally {
map.releaseLock();
}
}
else {
// Something's gone wrong and the lock isn't being released.
// We removed toClean from the queue and need to restore it
// TODO this is pretty dodgy
restorePendingPut(toClean);
}
}
}
}
private void restorePendingPut(PendingPut toRestore) {
pendingLock.lock();
try {
// Give it a new lease on life so it's not out of order. We could
// scan the queue and put toRestore back at the front, but then
// we'll just immediately try removing it again; instead we
// let it cycle through the queue again
toRestore.refresh();
pendingQueue.add(new WeakReference<PendingPut>(toRestore));
}
finally {
pendingLock.unlock();
}
}
/**
* Lazy-initialization map for PendingPut. Optimized for the expected usual
* case where only a single put is pending for a given key.
*
* This class is NOT THREAD SAFE. All operations on it must be performed
* with the lock held.
*/
private static class PendingPutMap {
private PendingPut singlePendingPut;
private Map<Object, PendingPut> fullMap;
private final Lock lock = new ReentrantLock();
PendingPutMap(PendingPut singleItem) {
this.singlePendingPut = singleItem;
}
public void put(PendingPut pendingPut) {
if (singlePendingPut == null) {
if (fullMap == null) {
// initial put
singlePendingPut = pendingPut;
} else {
fullMap.put(pendingPut.owner, pendingPut);
}
} else {
// 2nd put; need a map
fullMap = new HashMap<Object, PendingPut>(4);
fullMap.put(singlePendingPut.owner, singlePendingPut);
singlePendingPut = null;
fullMap.put(pendingPut.owner, pendingPut);
}
}
public PendingPut remove(Object ownerForPut) {
PendingPut removed = null;
if (fullMap == null) {
if (singlePendingPut != null
&& singlePendingPut.owner.equals(ownerForPut)) {
removed = singlePendingPut;
singlePendingPut = null;
}
} else {
removed = fullMap.remove(ownerForPut);
}
return removed;
}
public int size() {
return fullMap == null ? (singlePendingPut == null ? 0 : 1)
: fullMap.size();
}
public boolean acquireLock(long time, TimeUnit unit) {
try {
return lock.tryLock(time, unit);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
public void releaseLock() {
lock.unlock();
}
public void invalidate() {
if (singlePendingPut != null) {
singlePendingPut.completed = true;
}
else if (fullMap != null) {
for (PendingPut pp : fullMap.values()) {
pp.completed = true;
}
}
}
}
private static class PendingPut {
private final Object key;
private final Object owner;
private long timestamp = System.currentTimeMillis();
private volatile boolean completed;
private PendingPut(Object key, Object owner) {
this.key = key;
this.owner = owner;
}
private void refresh() {
timestamp = System.currentTimeMillis();
}
}
private static class RecentRemoval {
private final Object key;
private final Long timestamp;
private RecentRemoval(Object key, long nakedPutInvalidationPeriod) {
this.key = key;
timestamp = Long.valueOf(System.currentTimeMillis()
+ nakedPutInvalidationPeriod);
}
}
}

View File

@ -1,222 +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.jbc.access;
import javax.transaction.Transaction;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.jbc.BasicRegionAdapter;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.Option;
/**
* Defines the strategy for transactional access to entity or collection data in
* a pessimistic-locking JBoss Cache using its 2.x APIs.
* <p>
* The intent of this class is to encapsulate common code and serve as a
* delegate for {@link EntityRegionAccessStrategy} and
* {@link CollectionRegionAccessStrategy} implementations.
* </p>
*
* @author Brian Stansberry
*/
public class TransactionalAccessDelegate {
protected final Cache cache;
protected final Fqn regionFqn;
protected final boolean invalidation;
protected final BasicRegionAdapter region;
protected final PutFromLoadValidator putValidator;
public TransactionalAccessDelegate(BasicRegionAdapter adapter, PutFromLoadValidator validator) {
this.region = adapter;
this.cache = adapter.getCacheInstance();
this.regionFqn = adapter.getRegionFqn();
this.putValidator = validator;
this.invalidation = CacheHelper.isClusteredInvalidation(this.cache);
}
public Object get(Object key, long txTimestamp) throws CacheException {
if (!region.checkValid())
return null;
region.ensureRegionRootExists();
Object val = CacheHelper.get(cache, regionFqn, key);
if (val == null) {
putValidator.registerPendingPut(key);
}
return val;
}
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
if (!region.checkValid())
return false;
if (!putValidator.acquirePutFromLoadLock(key))
return false;
try {
region.ensureRegionRootExists();
return CacheHelper.putForExternalRead(cache, regionFqn, key, value);
}
finally {
putValidator.releasePutFromLoadLock(key);
}
}
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if (!region.checkValid())
return false;
if (!putValidator.acquirePutFromLoadLock(key))
return false;
try {
region.ensureRegionRootExists();
// We ignore minimalPutOverride. JBossCache putForExternalRead is
// already about as minimal as we can get; it will promptly return
// if it discovers that the node we want to write to already exists
return CacheHelper.putForExternalRead(cache, regionFqn, key, value);
}
finally {
putValidator.releasePutFromLoadLock(key);
}
}
public SoftLock lockItem(Object key, Object version) throws CacheException {
return null;
}
public SoftLock lockRegion() throws CacheException {
return null;
}
public void unlockItem(Object key, SoftLock lock) throws CacheException {
}
public void unlockRegion(SoftLock lock) throws CacheException {
}
public boolean insert(Object key, Object value, Object version) throws CacheException {
if (!region.checkValid())
return false;
region.ensureRegionRootExists();
if (invalidation) {
Option opt = new Option();
opt.setCacheModeLocal(true);
CacheHelper.put(cache, regionFqn, key, value, opt);
}
else {
CacheHelper.put(cache, regionFqn, key, value);
}
return true;
}
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
return false;
}
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);
return true;
}
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws CacheException {
return false;
}
public void remove(Object key) throws CacheException {
if (!putValidator.invalidateKey(key)) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for key " + key + " from region " + region.getName());
}
// 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 {
if (!putValidator.invalidateRegion()) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for region " + region.getName());
}
CacheHelper.removeAll(cache, regionFqn);
}
public void evict(Object key) throws CacheException {
if (!putValidator.invalidateKey(key)) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for key " + key + " from region " + region.getName());
}
region.ensureRegionRootExists();
CacheHelper.remove(cache, regionFqn, key);
}
public void evictAll() throws CacheException {
if (!putValidator.invalidateRegion()) {
throw new CacheException("Failed to invalidate pending putFromLoad calls for region " + region.getName());
}
Transaction tx = region.suspend();
try {
region.ensureRegionRootExists();
CacheHelper.sendEvictAllNotification(cache, regionFqn, region.getMemberId(), null);
}
finally {
region.resume(tx);
}
}
}

View File

@ -1,103 +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.jbc.builder;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.hibernate.cache.CacheException;
import org.hibernate.cfg.Settings;
import org.hibernate.internal.util.jndi.JndiHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.jboss.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A {@link MultiplexingCacheInstanceManager} that finds its cache factory
* in JNDI rather than creating one itself.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class JndiMultiplexingCacheInstanceManager extends MultiplexingCacheInstanceManager {
private static final Logger log = LoggerFactory.getLogger(JndiMultiplexingCacheInstanceManager.class);
/**
* Specifies the JNDI name under which the {@link CacheManager} to use is bound.
* There is no default value -- the user must specify the property.
*/
public static final String CACHE_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.cachefactory";
/**
* Create a new JndiMultiplexingCacheInstanceManager.
*/
public JndiMultiplexingCacheInstanceManager() {
super();
}
@Override
public void start(Settings settings, Properties properties) throws CacheException {
String name = ConfigurationHelper.getString(CACHE_FACTORY_RESOURCE_PROP, properties, null);
if (name == null)
throw new CacheException("Configuration property " + CACHE_FACTORY_RESOURCE_PROP + " not set");
CacheManager cf = locateCacheFactory( name, JndiHelper.extractJndiProperties( properties ) );
setCacheFactory( cf );
super.start(settings, properties);
}
private CacheManager locateCacheFactory(String jndiNamespace, Properties jndiProperties) {
Context ctx = null;
try {
ctx = new InitialContext( jndiProperties );
return (CacheManager) ctx.lookup( jndiNamespace );
}
catch (NamingException ne) {
String msg = "Unable to retreive Cache from JNDI [" + jndiNamespace + "]";
log.info( msg, ne );
throw new CacheException( msg );
}
finally {
if ( ctx != null ) {
try {
ctx.close();
}
catch( NamingException ne ) {
log.info( "Unable to release initial context", ne );
}
}
}
}
}

View File

@ -1,112 +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.jbc.builder;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.hibernate.cache.CacheException;
import org.hibernate.cfg.Settings;
import org.hibernate.internal.util.jndi.JndiHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.jboss.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A {@link SharedCacheInstanceManager} that finds the shared cache in JNDI
* rather than instantiating one from an XML config file.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class JndiSharedCacheInstanceManager extends SharedCacheInstanceManager {
private static final Logger log = LoggerFactory.getLogger(JndiSharedCacheInstanceManager.class);
/**
* Specifies the JNDI name under which the {@link Cache} to use is bound.
* <p>
* Note that although this configuration property has the same name as that by
* in {@link SharedCacheInstanceManager#CACHE_RESOURCE_PROP the superclass},
* the meaning here is different. Note also that in this class' usage
* of the property, there is no default value -- the user must specify
* the property.
*/
public static final String CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.shared";
/**
* Create a new JndiSharedCacheInstanceManager.
*
*/
public JndiSharedCacheInstanceManager() {
super();
}
@Override
protected Cache createSharedCache(Settings settings, Properties properties) {
String name = ConfigurationHelper.getString(CACHE_RESOURCE_PROP, properties, null);
if (name == null)
throw new CacheException("Configuration property " + CACHE_RESOURCE_PROP + " not set");
return locateCache( name, JndiHelper.extractJndiProperties( properties ) );
}
/**
* No-op; we don't own the cache so we shouldn't stop it.
*/
@Override
protected void stopSharedCache(Cache cache) {
// no-op. We don't own the cache so we shouldn't stop it.
}
private Cache locateCache(String jndiNamespace, Properties jndiProperties) {
Context ctx = null;
try {
ctx = new InitialContext( jndiProperties );
return (Cache) ctx.lookup( jndiNamespace );
}
catch (NamingException ne) {
String msg = "Unable to retreive Cache from JNDI [" + jndiNamespace + "]";
log.info( msg, ne );
throw new CacheException( msg );
}
finally {
if ( ctx != null ) {
try {
ctx.close();
}
catch( NamingException ne ) {
log.info( "Unable to release initial context", ne );
}
}
}
}
}

View File

@ -1,555 +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.jbc.builder;
import java.util.Properties;
import javax.transaction.TransactionManager;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheManager;
import org.jboss.cache.CacheManagerImpl;
import org.jboss.cache.CacheStatus;
import org.jboss.cache.config.Configuration;
import org.jgroups.ChannelFactory;
import org.jgroups.JChannelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.jbc.CacheInstanceManager;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cfg.Settings;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.transaction.TransactionManagerLookup;
/**
* Allows building separate {@link Cache} instances for each type of region,
* with the expectation that a single multiplexed JGroups resource (i.e. a
* multiplexed channel or a shared transport channel) will be shared between
* the caches.<p/>
*
* @author Steve Ebersole
* @author Brian Stansberry
*/
public class MultiplexingCacheInstanceManager implements CacheInstanceManager {
private static final Logger log = LoggerFactory.getLogger(MultiplexingCacheInstanceManager.class);
/**
* Classpath or filesystem resource containing JBoss Cache
* configurations the factory should use.
*
* @see #DEF_CACHE_FACTORY_RESOURCE
*/
public static final String CACHE_FACTORY_RESOURCE_PROP = "hibernate.cache.jbc.configs";
/**
* Legacy name for configuration property {@link #CACHE_FACTORY_RESOURCE_PROP}.
*
* @see #DEF_CACHE_FACTORY_RESOURCE
*/
public static final String LEGACY_CACHE_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.configs";
/**
* Classpath or filesystem resource containing JGroups protocol
* stack configurations the <code>org.jgroups.ChannelFactory</code>
* should use.
*
* @see #DEF_JGROUPS_RESOURCE
*/
public static final String CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.jbc.jgroups.stacks";
/**
* Legacy name for configuration property {@link #CHANNEL_FACTORY_RESOURCE_PROP}.
*
* @see #DEF_JGROUPS_RESOURCE
*/
public static final String LEGACY_CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.jgroups.stacks";
/**
* Name of the configuration that should be used for entity caches.
*
* @see #DEF_ENTITY_RESOURCE
*/
public static final String ENTITY_CACHE_RESOURCE_PROP = "hibernate.cache.jbc.cfg.entity";
/**
* Legacy name for configuration property {@link #ENTITY_CACHE_RESOURCE_PROP}.
*
* @see #DEF_ENTITY_RESOURCE
*/
public static final String LEGACY_ENTITY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.entity";
/**
* Name of the configuration that should be used for collection caches.
* No default value, as by default we try to use the same JBoss Cache
* instance we use for entity caching.
*
* @see #ENTITY_CACHE_RESOURCE_PROP
* @see #DEF_ENTITY_RESOURCE
*/
public static final String COLLECTION_CACHE_RESOURCE_PROP = "hibernate.cache.jbc.cfg.collection";
/**
* Legacy name for configuration property {@link #COLLECTION_CACHE_RESOURCE_PROP}.
*
* @see #ENTITY_CACHE_RESOURCE_PROP
* @see #DEF_ENTITY_RESOURCE
*/
public static final String LEGACY_COLLECTION_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.collection";
/**
* Name of the configuration that should be used for timestamp caches.
*
* @see #DEF_TS_RESOURCE
*/
public static final String TIMESTAMP_CACHE_RESOURCE_PROP = "hibernate.cache.jbc.cfg.timestamps";
/**
* Legacy name for configuration property {@link #TIMESTAMP_CACHE_RESOURCE_PROP}.
*
* @see #DEF_TS_RESOURCE
*/
public static final String LEGACY_TIMESTAMP_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.ts";
/**
* Name of the configuration that should be used for query caches.
*
* @see #DEF_QUERY_RESOURCE
*/
public static final String QUERY_CACHE_RESOURCE_PROP = "hibernate.cache.jbc.cfg.query";
/**
* Legacy name for configuration property {@link #QUERY_CACHE_RESOURCE_PROP}.
*
* @see #DEF_QUERY_RESOURCE
*/
public static final String LEGACY_QUERY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.query";
/**
* Default value for {@link #CACHE_FACTORY_RESOURCE_PROP}. Specifies
* the "jbc2-configs.xml" file in this package.
*/
public static final String DEF_CACHE_FACTORY_RESOURCE = "org/hibernate/cache/jbc/builder/jbc-configs.xml";
/**
* Default value for {@link #CHANNEL_FACTORY_RESOURCE_PROP}. Specifies
* the "jgroups-stacks.xml" file in this package.
*/
public static final String DEF_JGROUPS_RESOURCE = "org/hibernate/cache/jbc/builder/jgroups-stacks.xml";
/**
* Default value for {@link #ENTITY_CACHE_RESOURCE_PROP}.
*/
public static final String DEF_ENTITY_RESOURCE = "optimistic-entity";
/**
* Default value for {@link #TIMESTAMP_CACHE_RESOURCE_PROP}.
*/
public static final String DEF_TS_RESOURCE = "timestamps-cache";
/**
* Default value for {@link #ENTITY_CACHE_RESOURCE_PROP}.
*/
public static final String DEF_QUERY_RESOURCE = "local-query";
/** Cache for entities */
private Cache jbcEntityCache;
/** Cache for collections */
private Cache jbcCollectionCache;
/** Cache for timestamps */
private Cache jbcTsCache;
/** Cache for queries */
private Cache jbcQueryCache;
/** Name of config used for entities. */
private String entityConfig = null;
/** Name of config used for collections. */
private String collectionConfig = null;
/** Name of config used for queries. */
private String queryConfig = null;
/** Name of config used for timestamps. */
private String tsConfig = null;
/** Our cache factory */
private CacheManager jbcFactory;
/** Our channel factory */
private ChannelFactory channelFactory;
/**
* Did we create the factory ourself and thus can assume we are not
* sharing it (and the caches) with other users?
*/
private boolean selfCreatedFactory;
/**
* Create a new MultiplexingCacheInstanceManager.
*/
public MultiplexingCacheInstanceManager() {
}
/**
* Create a new MultiplexingCacheInstanceManager using the provided {@link Cache}s.
* <p/>
* If this constructor is used, the {@link #start(Settings, Properties)}
* method will make no attempt to create a cache factory or obtain caches
* from it. Only the <code>Cache</code>s passed as arguments to this
* constructor will be available.
*
* @param jbcEntityCache The entity cache
* @param jbcCollectionCache the collection cache
* @param jbcTsCache The timestamps cache
* @param jbcQueryCache The query cache
*/
public MultiplexingCacheInstanceManager(
Cache jbcEntityCache,
Cache jbcCollectionCache,
Cache jbcTsCache,
Cache jbcQueryCache) {
this.jbcEntityCache = jbcEntityCache;
this.jbcCollectionCache = jbcCollectionCache;
this.jbcTsCache = jbcTsCache;
this.jbcQueryCache = jbcQueryCache;
}
/**
* Getter for property 'cacheFactory'.
* @see #setCacheFactory
*
* @return Value for property 'cacheFactory'.
*/
public CacheManager getCacheFactory() {
return jbcFactory;
}
/**
* Setter for property 'cacheFactory'.
* @see #getCacheFactory
*
* @param factory Value to set for property 'cacheFactory'.
*/
public void setCacheFactory(CacheManager factory) {
this.jbcFactory = factory;
}
/**
* Getter for property 'channelFactory'.
* @see #setChannelFactory
*
* @return Value for property 'channelFactory'.
*/
public ChannelFactory getChannelFactory() {
return channelFactory;
}
/**
* Setter for property 'channelFactory'.
* @see #getChannelFactory
*
* @param factory Value to set for property 'channelFactory'.
*/
public void setChannelFactory(ChannelFactory factory) {
this.channelFactory = factory;
}
/**
* {@inheritDoc}
*/
public Cache getEntityCacheInstance() {
return jbcEntityCache;
}
/**
* {@inheritDoc}
*/
public Cache getCollectionCacheInstance() {
return jbcCollectionCache;
}
/**
* {@inheritDoc}
*/
public Cache getQueryCacheInstance() {
if (jbcQueryCache != null && jbcTsCache == null) {
// This should only be possible if the caches are constructor injected
throw new CacheException("Timestamps cache must be configured if a query cache is used");
}
return jbcQueryCache;
}
/**
* {@inheritDoc}
*/
public Cache getTimestampsCacheInstance() {
if (jbcTsCache != null && CacheHelper.isClusteredInvalidation(jbcTsCache)) {
throw new CacheException("Clustered invalidation not supported for timestamps cache");
}
return jbcTsCache;
}
/**
* {@inheritDoc}
*/
public void start(Settings settings, Properties properties) throws CacheException {
try {
// We need our tm, so get it now and avoid doing other work
// if there is a problem
TransactionManagerLookup tml = settings.getTransactionManagerLookup();
TransactionManager tm = (tml == null ? null : tml.getTransactionManager(properties));
// We only build caches if *none* were passed in. Passing in
// caches counts as a clear statement of exactly what is wanted
boolean buildCaches = jbcEntityCache == null
&& jbcCollectionCache == null
&& jbcTsCache == null
&& jbcQueryCache == null;
// Set up the cache factory
if (buildCaches && jbcFactory == null) {
// See if the user configured a multiplexer stack
if (channelFactory == null) {
String muxStacks = ConfigurationHelper.getString(CHANNEL_FACTORY_RESOURCE_PROP, properties, null);
if (muxStacks == null) {
muxStacks = ConfigurationHelper.getString(LEGACY_CHANNEL_FACTORY_RESOURCE_PROP, properties, DEF_JGROUPS_RESOURCE);
}
if (muxStacks != null) {
channelFactory = new JChannelFactory();
channelFactory.setMultiplexerConfig(muxStacks);
}
}
String factoryRes = ConfigurationHelper.getString(CACHE_FACTORY_RESOURCE_PROP, properties, null);
if (factoryRes == null) {
factoryRes = ConfigurationHelper.getString(LEGACY_CACHE_FACTORY_RESOURCE_PROP, properties, DEF_CACHE_FACTORY_RESOURCE);
}
jbcFactory = new CacheManagerImpl(factoryRes, channelFactory);
((CacheManagerImpl) jbcFactory).start();
selfCreatedFactory = true;
}
if (settings.isSecondLevelCacheEnabled()) {
if (buildCaches) {
entityConfig = ConfigurationHelper
.getString(ENTITY_CACHE_RESOURCE_PROP, properties, null);
if (entityConfig == null) {
entityConfig = ConfigurationHelper.getString(LEGACY_ENTITY_CACHE_RESOURCE_PROP,
properties, DEF_ENTITY_RESOURCE);
}
jbcEntityCache = jbcFactory.getCache(entityConfig, true);
// Default to collections sharing entity cache if there is one
collectionConfig = ConfigurationHelper.getString(COLLECTION_CACHE_RESOURCE_PROP, properties, null);
if (collectionConfig == null) {
collectionConfig = ConfigurationHelper.getString(LEGACY_COLLECTION_CACHE_RESOURCE_PROP, properties, entityConfig);
}
if (entityConfig.equals(collectionConfig)) {
jbcCollectionCache = jbcEntityCache;
}
else {
jbcCollectionCache = jbcFactory.getCache(collectionConfig, true);
}
}
if (jbcEntityCache != null) {
configureTransactionManager(jbcEntityCache, tm, false);
jbcEntityCache.start();
}
if (jbcCollectionCache != null) {
configureTransactionManager(jbcCollectionCache, tm, false);
jbcCollectionCache.start();
}
}
else {
jbcEntityCache = null;
jbcCollectionCache = null;
}
if (settings.isQueryCacheEnabled()) {
if (buildCaches) {
// Default to sharing the entity cache if there is one
String dfltQueryResource = (entityConfig == null ? DEF_QUERY_RESOURCE : entityConfig);
queryConfig = ConfigurationHelper.getString(QUERY_CACHE_RESOURCE_PROP, properties, null);
if (queryConfig == null) {
queryConfig = ConfigurationHelper.getString(LEGACY_QUERY_CACHE_RESOURCE_PROP, properties, dfltQueryResource);
}
if (queryConfig.equals(entityConfig)) {
jbcQueryCache = jbcEntityCache;
} else if (queryConfig.equals(collectionConfig)) {
jbcQueryCache = jbcCollectionCache;
} else {
jbcQueryCache = jbcFactory.getCache(queryConfig, true);
}
// For Timestamps, we default to a separate config
tsConfig = ConfigurationHelper.getString(TIMESTAMP_CACHE_RESOURCE_PROP, properties, null);
if (tsConfig == null) {
tsConfig = ConfigurationHelper.getString(LEGACY_TIMESTAMP_CACHE_RESOURCE_PROP, properties, DEF_TS_RESOURCE);
}
if (tsConfig.equals(queryConfig)) {
jbcTsCache = jbcQueryCache;
}
else if (tsConfig.equals(entityConfig)) {
jbcTsCache = jbcEntityCache;
}
else if (tsConfig.equals(collectionConfig)) {
jbcTsCache = jbcCollectionCache;
}
else {
jbcTsCache = jbcFactory.getCache(tsConfig, true);
}
}
if (jbcQueryCache != null) {
configureTransactionManager(jbcQueryCache, tm, false);
jbcQueryCache.start();
// TODO: I considered validating the presence of the TS cache here,
// but decided to defer unti getQueryCacheInstance() in case the
// cache is never actually used
}
if (jbcTsCache != null) {
configureTransactionManager(jbcTsCache, tm, true);
jbcTsCache.start();
// TODO: I considered validating TS cache config here,
// but decided to defer unti getTimestampsCacheInstance() in case the
// cache is never actually used
}
}
else {
jbcTsCache = null;
jbcQueryCache = null;
}
}
catch (CacheException ce) {
throw ce;
}
catch (Throwable t) {
throw new CacheException("Unable to start region factory", t);
}
}
/**
* {@inheritDoc}
*/
public void stop() {
releaseCaches();
if (selfCreatedFactory) {
((CacheManagerImpl) jbcFactory).stop();
}
}
/**
* Injects the given TransactionManager into the cache.
*
* @param cache the cache. cannot be <code>null</code>
* @param tm the transaction manager Hibernate recognizes
* May be <code>null</code>
* @param allowNull whether we accept a null transaction manager in the cache
* if <code>tm</code> is not <code>null</code>
*
* @throws CacheException if <code>cache</code> is already started and is
* configured with a different TransactionManager
* than the one we would inject
*/
private void configureTransactionManager(Cache cache, TransactionManager tm, boolean allowNull) {
Configuration cacheConfig = cache.getConfiguration();
TransactionManager cacheTm = cacheConfig.getRuntimeConfig().getTransactionManager();
if (!safeEquals(tm, cacheTm)) {
if (cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
// We can't change the TM on a running cache; just check
// if the cache has no TM and we're OK with that
if (!allowNull && cacheTm == null) {
throw new CacheException("JBoss Cache is already started with no transaction manager configured");
} else {
log.debug("JBoss Cache is already started with a transaction manager ("
+ cacheTm + ") that is not equal to our own (" + tm + ")");
}
} else {
// Configure the cache to use our TM
cacheConfig.getRuntimeConfig().setTransactionManager(tm);
if (tm == null) {
// Make sure JBC doesn't look one up
cacheConfig.setTransactionManagerLookupClass(null);
}
}
}
}
/**
* Notify cache factory that we are no longer using the caches.
*/
private void releaseCaches() {
// This method should be implemented assuming it's valid to
// do start/stop/start -- leave state appropriate for another start
if (jbcEntityCache != null && entityConfig != null) {
try {
jbcFactory.releaseCache(entityConfig);
jbcEntityCache = null;
// Make sure we don't re-release the same cache
if (entityConfig.equals(collectionConfig))
collectionConfig = null;
if (entityConfig.equals(queryConfig))
queryConfig = null;
if (entityConfig.equals(tsConfig))
tsConfig = null;
entityConfig = null;
} catch (Throwable t) {
log.info("Unable to release entity cache instance", t);
}
}
if (jbcCollectionCache != null && collectionConfig != null) {
try {
jbcFactory.releaseCache(collectionConfig);
jbcCollectionCache = null;
if (collectionConfig.equals(queryConfig))
queryConfig = null;
if (collectionConfig.equals(tsConfig))
tsConfig = null;
collectionConfig = null;
} catch (Throwable t) {
log.info("Unable to stop collection cache instance", t);
}
}
if (jbcQueryCache != null && queryConfig != null) {
try {
jbcFactory.releaseCache(queryConfig);
jbcQueryCache = null;
if (queryConfig.equals(tsConfig))
tsConfig = null;
queryConfig = null;
} catch (Throwable t) {
log.info("Unable to stop query cache instance", t);
}
}
if (jbcTsCache != null && tsConfig != null) {
try {
jbcFactory.releaseCache(tsConfig);
jbcTsCache = null;
tsConfig = null;
} catch (Throwable t) {
log.info("Unable to stop timestamp cache instance", t);
}
}
}
private boolean safeEquals(Object a, Object b) {
return (a == b || (a != null && a.equals(b)));
}
}

View File

@ -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.jbc.builder;
import java.util.Properties;
import javax.transaction.TransactionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheStatus;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.config.Configuration;
import org.jgroups.ChannelFactory;
import org.jgroups.JChannelFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.jbc.CacheInstanceManager;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cfg.Settings;
import org.hibernate.internal.util.config.ConfigurationHelper;
/**
* A {@link CacheInstanceManager} implementation where we use a single JBoss Cache
* instance for each type of region. If operating on a cluster, the cache must
* be configured for REPL_SYNC if query caching is enabled. If query caching
* is not used, REPL_SYNC or INVALIDATION_SYNC are valid, with
* INVALIDATION_SYNC preferred.
*
* @author Steve Ebersole
* @author Brian Stansberry
*/
public class SharedCacheInstanceManager implements CacheInstanceManager {
private static final Logger log = LoggerFactory.getLogger(SharedCacheInstanceManager.class);
/**
* Classpath or filesystem resource containing JBoss Cache
* configuration settings the {@link Cache} should use.
*
* @see #DEFAULT_CACHE_RESOURCE
*/
public static final String CACHE_RESOURCE_PROP = "hibernate.cache.jbc.cfg.shared";
/**
* Legacy name for configuration property {@link #CACHE_RESOURCE_PROP}.
*
* @see #DEFAULT_CACHE_RESOURCE
*/
public static final String LEGACY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.shared";
/**
* Default name for the JBoss Cache configuration file.
*/
public static final String DEFAULT_CACHE_RESOURCE = "treecache.xml";
/**
* Classpath or filesystem resource containing JGroups protocol
* stack configurations the <code>org.jgroups.ChannelFactory</code>
* should use.
*
* @see #DEF_JGROUPS_RESOURCE
*/
public static final String CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.jbc.cfg.jgroups.stacks";
/**
* Legacy name for configuration property {@link #CHANNEL_FACTORY_RESOURCE_PROP}.
*
* @see #DEF_JGROUPS_RESOURCE
*/
public static final String LEGACY_CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.jgroups.stacks";
/**
* Default value for {@link #CHANNEL_FACTORY_RESOURCE_PROP}. Specifies
* the "jgroups-stacks.xml" file in this package.
*/
public static final String DEF_JGROUPS_RESOURCE = "org/hibernate/cache/jbc/builder/jgroups-stacks.xml";
private Cache cache;
private ChannelFactory channelFactory;
private boolean use2ndLevel;
private boolean useQuery;
public SharedCacheInstanceManager() {
}
public SharedCacheInstanceManager(ChannelFactory channelFactory) {
this.channelFactory = channelFactory;
}
public SharedCacheInstanceManager(Cache cache) {
this.cache = cache;
}
/**
* {@inheritDoc}
*/
public Cache getEntityCacheInstance() {
return use2ndLevel ? cache : null;
}
/**
* {@inheritDoc}
*/
public Cache getCollectionCacheInstance() {
return use2ndLevel ? cache : null;
}
/**
* {@inheritDoc}
*/
public Cache getQueryCacheInstance() {
if (!useQuery)
return null;
if (CacheHelper.isClusteredInvalidation(cache)) {
throw new CacheException("Query cache not supported for clustered invalidation");
}
return cache;
}
/**
* {@inheritDoc}
*/
public void start(Settings settings, Properties properties) throws CacheException {
use2ndLevel = settings.isSecondLevelCacheEnabled();
useQuery = settings.isQueryCacheEnabled();
if (cache == null) {
if (channelFactory == null) {
String muxStacks = ConfigurationHelper.getString(CHANNEL_FACTORY_RESOURCE_PROP, properties, null);
if (muxStacks == null) {
ConfigurationHelper.getString(LEGACY_CHANNEL_FACTORY_RESOURCE_PROP, properties, DEF_JGROUPS_RESOURCE);
}
if (muxStacks != null) {
channelFactory = new JChannelFactory();
try {
channelFactory.setMultiplexerConfig(muxStacks);
}
catch (Exception e) {
throw new CacheException("Problem setting ChannelFactory config", e);
}
}
}
cache = createSharedCache(settings, properties);
configureTransactionManager(cache, settings, properties);
if (cache.getConfiguration().getMultiplexerStack() != null
&& cache.getConfiguration().getRuntimeConfig().getMuxChannelFactory() == null) {
cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(channelFactory);
}
}
cache.start();
}
/**
* {@inheritDoc}
*/
public Cache getTimestampsCacheInstance() {
if (!useQuery)
return null;
if (CacheHelper.isClusteredInvalidation(cache)) {
throw new CacheException("Query cache not supported for clustered invalidation");
}
return cache;
}
/**
* {@inheritDoc}
*/
public void stop() {
if (cache != null) {
stopSharedCache(cache);
}
}
/**
* Create a cache using the given settings and properties.
*
* @param settings The Hibernate settings
* @param properties The configuration properties
* @return The created cache
*/
protected Cache createSharedCache(Settings settings, Properties properties)
{
String configResource = ConfigurationHelper.getString(CACHE_RESOURCE_PROP, properties, null);
if (configResource == null) {
configResource = ConfigurationHelper.getString(LEGACY_CACHE_RESOURCE_PROP, properties, DEFAULT_CACHE_RESOURCE);
}
return new DefaultCacheFactory().createCache(configResource, false);
}
/**
* Injects the TransactionManager found via {@link Settings#getTransactionManagerLookup()}
* into the cache.
*
* @param cache The cache instance
* @param settings The Hibernate settings
* @param properties The configuration properties
*
* @throws CacheException if <code>cache</code> is already started and is
* configured with a different TransactionManager
* than the one we would inject
*/
protected void configureTransactionManager(Cache cache, Settings settings, Properties properties) {
TransactionManager tm = null;
if (settings.getTransactionManagerLookup() != null) {
tm = settings.getTransactionManagerLookup().getTransactionManager(properties);
}
Configuration cacheConfig = cache.getConfiguration();
TransactionManager cacheTm = cacheConfig.getRuntimeConfig().getTransactionManager();
if (!safeEquals(tm, cacheTm)) {
if (cache.getCacheStatus() != CacheStatus.INSTANTIATED
&& cache.getCacheStatus() != CacheStatus.DESTROYED) {
log.debug("JBoss Cache is already started with a transaction manager ("
+ cacheTm + ") that is not equal to our own (" + tm + ")");
} else {
// Configure the cache to use our TM
cacheConfig.getRuntimeConfig().setTransactionManager(tm);
if (tm == null) {
// Make sure JBC doesn't look one up
cacheConfig.setTransactionManagerLookupClass(null);
}
}
}
}
private boolean safeEquals(Object a, Object b) {
return (a == b || (a != null && a.equals(b)));
}
/**
* Stops the shared cache.
* @param cache the shared cache
*/
protected void stopSharedCache(Cache cache) {
try {
if (cache.getCacheStatus() == CacheStatus.STARTED) {
cache.stop();
}
if (cache.getCacheStatus() != CacheStatus.DESTROYED
&& cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
cache.destroy();
}
} catch (Throwable t) {
log.warn("Unable to stop cache instance", t);
}
}
}

View File

@ -1,76 +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.jbc.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;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.jbc.TransactionalDataRegionAdapter;
import org.hibernate.cache.jbc.access.PutFromLoadValidator;
/**
* Defines the behavior of the collection cache regions for JBossCache 2.x.
*
* @author Steve Ebersole
*/
@CacheListener
public class CollectionRegionImpl extends TransactionalDataRegionAdapter implements CollectionRegion {
public static final String TYPE = "COLL";
private boolean optimistic;
public CollectionRegionImpl(Cache jbcCache, String regionName, String regionPrefix, CacheDataDescription metadata) {
super(jbcCache, regionName, regionPrefix, metadata);
optimistic = (jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC);
}
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
if (AccessType.READ_ONLY.equals(accessType)) {
return optimistic ? new OptimisticReadOnlyAccess(this) : new ReadOnlyAccess(this);
}
if (AccessType.TRANSACTIONAL.equals(accessType)) {
return optimistic ? new OptimisticTransactionalAccess(this) : new TransactionalAccess(this);
}
// todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
throw new CacheException("unsupported access type [" + accessType.getName() + "]");
}
@Override
protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
return getTypeLastRegionFqn(regionName, regionPrefix, TYPE);
}
public PutFromLoadValidator getPutFromLoadValidator() {
return new PutFromLoadValidator(transactionManager);
}
}

View File

@ -1,71 +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.jbc.collection;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.access.SoftLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This defines the strategy for transactional access to collection data in an
* optimistic-locking JBossCache using its 2.x APIs. <p/> The read-only access
* to a JBossCache really is still transactional, just with the extra semantic
* or guarantee that we will not update data.
*
* @author Brian Stansberry
*/
public class OptimisticReadOnlyAccess extends OptimisticTransactionalAccess {
private static final Logger log = LoggerFactory.getLogger(OptimisticReadOnlyAccess.class);
/**
* Create a new OptimisticReadOnlyAccess.
*
* @param region The region to which this is providing access
*/
public OptimisticReadOnlyAccess(CollectionRegionImpl region) {
super(region);
}
@Override
public SoftLock lockItem(Object key, Object version) throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
@Override
public SoftLock lockRegion() throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only region");
}
@Override
public void unlockItem(Object key, SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only item");
}
@Override
public void unlockRegion(SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only region");
}
}

View File

@ -1,48 +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.jbc.collection;
import org.hibernate.cache.jbc.access.OptimisticTransactionalAccessDelegate;
/**
* Defines the strategy for transactional access to entity data in an
* optimistic-locking JBoss Cache using its 2.x APIs
*
* @author Brian Stansberry
* @version $Revision: 1 $
*/
public class OptimisticTransactionalAccess extends TransactionalAccess {
/**
* Create a new OptimisticTransactionalAccess.
*
* @param region The region to which this is providing access
*/
public OptimisticTransactionalAccess(CollectionRegionImpl region) {
// We use a different delegate than the non-optimistic superclass default
super(region, new OptimisticTransactionalAccessDelegate(region, region.getPutFromLoadValidator()));
}
}

View File

@ -1,83 +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.jbc.collection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.CacheException;
/**
* This defines the strategy for transactional access to collection data in a
* pessimistic-locking JBossCache using its 2.x APIs. <p/> The read-only access
* to a JBossCache really is still transactional, just with the extra semantic
* or guarantee that we will not update data.
*
* @author Steve Ebersole
*/
public class ReadOnlyAccess extends TransactionalAccess {
private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
/**
* Create a provider of read-only access to the specific region.
*
* @param region The region to which this provides access.
*/
public ReadOnlyAccess(CollectionRegionImpl region) {
super(region);
}
/**
* {@inheritDoc}
*/
@Override
public SoftLock lockItem(Object key, Object version) throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
/**
* {@inheritDoc}
*/
@Override
public SoftLock lockRegion() throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only region");
}
/**
* {@inheritDoc}
*/
@Override
public void unlockItem(Object key, SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only item");
}
/**
* {@inheritDoc}
*/
@Override
public void unlockRegion(SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only region");
}
}

View File

@ -1,155 +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.jbc.collection;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.jbc.access.TransactionalAccessDelegate;
/**
* This defines the strategy for transactional access to collection data in a
* pessimistic-locking JBossCache using its 2.x APIs
*
* @author Steve Ebersole
* @author Brian Stansberry
*/
public class TransactionalAccess implements CollectionRegionAccessStrategy {
private final CollectionRegionImpl region;
/**
* Most of our logic is shared between this and entity regions, so we
* delegate to a class that encapsulates it
*/
private final TransactionalAccessDelegate delegate;
/**
* Create a new TransactionalAccess.
*
* @param region the region to which this provides access
*/
public TransactionalAccess(CollectionRegionImpl region) {
this(region, new TransactionalAccessDelegate(region, region.getPutFromLoadValidator()));
}
/**
* Allow subclasses to define the delegate.
*
* @param region the region to which this provides access
* @param delegate type of transactional access
*/
protected TransactionalAccess(CollectionRegionImpl region, TransactionalAccessDelegate delegate) {
this.region = region;
this.delegate = delegate;
}
/**
* {@inheritDoc}
*/
public CollectionRegion getRegion() {
return region;
}
/**
* {@inheritDoc}
*/
public Object get(Object key, long txTimestamp) throws CacheException {
return delegate.get(key, txTimestamp);
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
return delegate.putFromLoad(key, value, txTimestamp, version);
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
}
/**
* {@inheritDoc}
*/
public void remove(Object key) throws CacheException {
delegate.remove(key);
}
/**
* {@inheritDoc}
*/
public void removeAll() throws CacheException {
delegate.removeAll();
}
/**
* {@inheritDoc}
*/
public void evict(Object key) throws CacheException {
delegate.evict(key);
}
/**
* {@inheritDoc}
*/
public void evictAll() throws CacheException {
delegate.evictAll();
}
/**
* {@inheritDoc}
*/
public SoftLock lockItem(Object key, Object version) throws CacheException {
return null;
}
/**
* {@inheritDoc}
*/
public SoftLock lockRegion() throws CacheException {
return null;
}
/**
* {@inheritDoc}
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
}
/**
* {@inheritDoc}
*/
public void unlockRegion(SoftLock lock) throws CacheException {
}
}

View File

@ -1,81 +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.jbc.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;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.jbc.TransactionalDataRegionAdapter;
import org.hibernate.cache.jbc.access.PutFromLoadValidator;
/**
* Defines the behavior of the entity cache regions for JBossCache.
*
* @author Steve Ebersole
*/
@CacheListener
public class EntityRegionImpl extends TransactionalDataRegionAdapter implements EntityRegion {
public static final String TYPE = "ENTITY";
private boolean optimistic;
public EntityRegionImpl(Cache jbcCache, String regionName, String regionPrefix, CacheDataDescription metadata) {
super(jbcCache, regionName, regionPrefix, metadata);
optimistic = (jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC);
}
/**
* {@inheritDoc}
*/
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
if (AccessType.READ_ONLY.equals(accessType)) {
return optimistic ? new OptimisticReadOnlyAccess(this) : new ReadOnlyAccess(this);
}
if (AccessType.TRANSACTIONAL.equals(accessType)) {
return optimistic ? new OptimisticTransactionalAccess(this) : new TransactionalAccess(this);
}
// todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
throw new CacheException("unsupported access type [" + accessType.getName() + "]");
}
@Override
protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
return getTypeLastRegionFqn(regionName, regionPrefix, TYPE);
}
public PutFromLoadValidator getPutFromLoadValidator() {
return new PutFromLoadValidator(transactionManager);
}
}

View File

@ -1,78 +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.jbc.entity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.CacheException;
/**
* This defines the strategy for read-only access to enity data in an
* optimistic-locking JBossCache using its 2.x APIs <p/> The read-only access to
* a JBossCache really is still transactional, just with the extra semantic or
* guarantee that we will not update data.
*
* @author Brian Stansberry
*/
public class OptimisticReadOnlyAccess extends OptimisticTransactionalAccess {
private static final Logger log = LoggerFactory.getLogger(OptimisticReadOnlyAccess.class);
public OptimisticReadOnlyAccess(EntityRegionImpl region) {
super(region);
}
@Override
public SoftLock lockItem(Object key, Object version) throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
@Override
public SoftLock lockRegion() throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only region");
}
@Override
public void unlockItem(Object key, SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only item");
}
@Override
public void unlockRegion(SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only region");
}
@Override
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
@Override
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
}

View File

@ -1,46 +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.jbc.entity;
import org.hibernate.cache.jbc.access.OptimisticTransactionalAccessDelegate;
/**
* Defines the strategy for transactional access to entity data in an
* optimistic-locking JBoss Cache using its 2.x APIs
*
* @author Brian Stansberry
* @version $Revision: 1 $
*/
public class OptimisticTransactionalAccess extends TransactionalAccess {
/**
* Create a new OptimisticTransactionalAccess.
*
* @param region The region\ to which this is providing access
*/
public OptimisticTransactionalAccess(EntityRegionImpl region) {
super(region, new OptimisticTransactionalAccessDelegate(region, region.getPutFromLoadValidator()));
}
}

View File

@ -1,78 +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.jbc.entity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.CacheException;
/**
* This defines the strategy for transactional access to enity data in
* JBossCache using its 2.x APIs <p/> read-only access to a JBossCache really is
* still transactional, just with the extra semantic or guarentee that we will
* not update data.
*
* @author Steve Ebersole
*/
public class ReadOnlyAccess extends TransactionalAccess {
private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
public ReadOnlyAccess(EntityRegionImpl region) {
super(region);
}
@Override
public SoftLock lockItem(Object key, Object version) throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
@Override
public SoftLock lockRegion() throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only region");
}
@Override
public void unlockItem(Object key, SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only item");
}
@Override
public void unlockRegion(SoftLock lock) throws CacheException {
log.error("Illegal attempt to edit read only region");
}
@Override
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
@Override
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws CacheException {
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
}
}

View File

@ -1,130 +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.jbc.entity;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.jbc.access.TransactionalAccessDelegate;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.CacheException;
/**
* Defines the strategy for transactional access to entity data in a
* pessimistic-locking JBossCache using its 2.x APIs
*
* @author Steve Ebersole
*/
public class TransactionalAccess implements EntityRegionAccessStrategy {
protected final EntityRegionImpl region;
/**
* Most of our logic is shared between this and entity regions, so we
* delegate to a class that encapsulates it
*/
private final TransactionalAccessDelegate delegate;
public TransactionalAccess(EntityRegionImpl region) {
this(region, new TransactionalAccessDelegate(region, region.getPutFromLoadValidator()));
}
protected TransactionalAccess(EntityRegionImpl region, TransactionalAccessDelegate delegate) {
this.region = region;
this.delegate = delegate;
}
public EntityRegion getRegion() {
return region;
}
public Object get(Object key, long txTimestamp) throws CacheException {
return delegate.get(key, txTimestamp);
}
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
return delegate.putFromLoad(key, value, txTimestamp, version);
}
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
}
public boolean insert(Object key, Object value, Object version) throws CacheException {
return delegate.insert(key, value, version);
}
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
return delegate.update(key, value, currentVersion, previousVersion);
}
public void remove(Object key) throws CacheException {
delegate.remove(key);
}
public void removeAll() throws CacheException {
delegate.removeAll();
}
public void evict(Object key) throws CacheException {
delegate.evict(key);
}
public void evictAll() throws CacheException {
delegate.evictAll();
}
// Following methods we don't delegate since they have so little logic
// it's clearer to just implement them here
public SoftLock lockItem(Object key, Object version) throws CacheException {
return null;
}
public SoftLock lockRegion() throws CacheException {
return null;
}
public void unlockItem(Object key, SoftLock lock) throws CacheException {
}
public void unlockRegion(SoftLock lock) throws CacheException {
}
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
return false;
}
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws CacheException {
return false;
}
}

View File

@ -1,160 +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.jbc.query;
import java.util.Properties;
import javax.transaction.Transaction;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.jbc.TransactionalDataRegionAdapter;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
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.
*
* @author Brian Stansberry
* @version $Revision$
*/
@CacheListener
public class QueryResultsRegionImpl extends TransactionalDataRegionAdapter implements QueryResultsRegion {
public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.jbc.query.localonly";
public static final String LEGACY_QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.region.jbc2.query.localonly";
public static final String TYPE = "QUERY";
/**
* Whether we should set an option to disable propagation of changes around
* cluster.
*/
private boolean localOnly;
/**
* Create a new QueryResultsRegionImpl.
*
* @param jbcCache The JBC cache instance to use to store the query results
* @param regionName The name of the region (within the JBC cache)
* @param regionPrefix Any region prefix to apply
* @param properties The configuration properties.
*/
public QueryResultsRegionImpl(Cache jbcCache, String regionName, String regionPrefix, Properties properties) {
super(jbcCache, regionName, regionPrefix, null);
// If JBC is using INVALIDATION, we don't want to propagate changes.
// We use the Timestamps cache to manage invalidation
localOnly = CacheHelper.isClusteredInvalidation(jbcCache);
if (!localOnly) {
// We don't want to waste effort setting an option if JBC is
// already in LOCAL mode. If JBC is REPL_(A)SYNC then check
// if they passed an config option to disable query replication
if (CacheHelper.isClusteredReplication(jbcCache)) {
if (properties.containsKey(QUERY_CACHE_LOCAL_ONLY_PROP)) {
localOnly = ConfigurationHelper.getBoolean(QUERY_CACHE_LOCAL_ONLY_PROP, properties, false);
}
else {
localOnly = ConfigurationHelper.getBoolean(LEGACY_QUERY_CACHE_LOCAL_ONLY_PROP, properties, false);
}
}
}
}
public void evict(Object key) throws CacheException {
ensureRegionRootExists();
Option opt = getNonLockingDataVersionOption(false);
if (localOnly)
opt.setCacheModeLocal(true);
CacheHelper.removeNode(getCacheInstance(), getRegionFqn(), key, opt);
}
public void evictAll() throws CacheException {
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
// prevents updates
// Add a zero (or low) timeout option so we don't block
// waiting for tx's that did a put to commit
Option opt = new Option();
opt.setLockAcquisitionTimeout(0);
return suspendAndGet(key, opt, true);
}
public void put(Object key, Object value) throws CacheException {
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
protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
return getTypeLastRegionFqn(regionName, regionPrefix, TYPE);
}
}

View File

@ -1,361 +0,0 @@
/*
* Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
*
* 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, v. 2.1. This program is distributed in the
* hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
* distribution; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Red Hat Author(s): Brian Stansberry
*/
package org.hibernate.cache.jbc.timestamp;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import javax.transaction.Transaction;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.TimestampsRegion;
import org.hibernate.cache.jbc.TransactionalDataRegionAdapter;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
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.NodeModifiedEvent;
import org.jboss.cache.notifications.event.NodeRemovedEvent;
/**
* Prototype of a clustered timestamps cache region impl usable if the
* TimestampsRegion API is changed.
* <p>
* Maintains a local (authoritative) cache of timestamps along with the
* distributed cache held in JBoss Cache. Listens for changes in the distributed
* cache and updates the local cache accordingly. Ensures that any changes in
* the local cache represent either 1) an increase in the timestamp or
* 2) a stepback in the timestamp by the caller that initially increased
* it as part of a pre-invalidate call. This approach allows
* timestamp changes to be replicated asynchronously by JBoss Cache while still
* preventing invalid backward changes in timestamps.
* </p>
*
* NOTE: This is just a prototype!!! Only useful if we change the
* TimestampsRegion API.
*
* @author Brian Stansberry
* @version $Revision: 14106 $
*/
@CacheListener
public class ClusteredConcurrentTimestampsRegionImpl extends TransactionalDataRegionAdapter implements TimestampsRegion {
public static final String TYPE = "TS";
private final ConcurrentHashMap localCache = new ConcurrentHashMap();
/**
* Create a new ClusteredConccurentTimestampsRegionImpl.
*
* @param jbcCache
* @param regionName
* @param regionPrefix
* TODO
* @param metadata
*/
public ClusteredConcurrentTimestampsRegionImpl(Cache jbcCache, String regionName, String regionPrefix, Properties properties) {
super(jbcCache, regionName, regionPrefix, null);
jbcCache.addCacheListener(this);
populateLocalCache();
}
@Override
protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
return getTypeFirstRegionFqn(regionName, regionPrefix, TYPE);
}
public void evict(Object key) throws CacheException {
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.removeNode(getCacheInstance(), getRegionFqn(), key, opt);
}
public void evictAll() throws CacheException {
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
}
public Object get(Object key) throws CacheException {
Entry entry = getLocalEntry(key);
Object timestamp = entry.getCurrent();
if (timestamp == null) {
// Double check the distributed cache
Object[] vals = (Object[]) suspendAndGet(key, null, false);
if (vals != null) {
storeDataFromJBC(key, vals);
timestamp = entry.getCurrent();
}
}
return timestamp;
}
public void put(Object key, Object value) throws CacheException {
throw new UnsupportedOperationException("Prototype only; Hibernate core must change the API before really using");
}
public void preInvalidate(Object key, Object value) throws CacheException {
Entry entry = getLocalEntry(key);
if (entry.preInvalidate(value)) {
putInJBossCache(key, entry);
}
}
public void invalidate(Object key, Object value, Object preInvalidateValue) throws CacheException {
Entry entry = getLocalEntry(key);
if (entry.invalidate(value, preInvalidateValue)) {
putInJBossCache(key, entry);
}
}
private void putInJBossCache(Object key, Entry entry) {
// Get an exclusive right to update JBC for this key from this node.
boolean locked = false;
try {
entry.acquireJBCWriteMutex();
locked = true;
// We have the JBCWriteMutex, so no other *local* thread will
// be trying to write this key.
// It's possible here some remote thread has come in and
// changed the values again, but since we are reading the
// values to write to JBC right now, we know we are writing
// the latest values; i.e. we don't assume that what we cached
// in entry.update() above is what we should write to JBC *now*.
// Our write could be redundant, i.e. we are writing what
// some remote thread just came in an wrote. There is a chance
// that yet another remote thread will update us, and we'll then
// overwrite that later data in JBC. But, all remote nodes will
// ignore that change in their localCache; the only place it
// will live will be in JBC, where it can only effect the
// initial state transfer values on newly joined nodes
// (i.e. populateLocalCache()).
// Don't hold the JBC node lock throughout the tx, as that
// prevents reads and other updates
Transaction tx = suspend();
try {
Option opt = getNonLockingDataVersionOption(false);
// We ensure ASYNC semantics (JBCACHE-1175)
opt.setForceAsynchronous(true);
CacheHelper.put(getCacheInstance(), getRegionFqn(), key, entry.getJBCUpdateValues(), opt);
}
finally {
resume(tx);
}
}
catch (InterruptedException e) {
throw new CacheException("Interrupted while acquiring right to update " + key, e);
}
finally {
if (locked) {
entry.releaseJBCWriteMutex();
}
}
}
@Override
public void destroy() throws CacheException {
getCacheInstance().removeCacheListener(this);
super.destroy();
localCache.clear();
}
/**
* Monitors cache events and updates the local cache
*
* @param event
*/
@NodeModified
public void nodeModified(NodeModifiedEvent event) {
if (event.isOriginLocal() || 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());
Object[] vals = (Object[]) event.getData().get(ITEM);
storeDataFromJBC(key, vals);
// TODO consider this hack instead of the simple entry.update above:
// if (!entry.update(vals[0], vals[1])) {
// // Hack! Use the fact that the Object[] stored in JBC is
// // mutable to correct our local JBC state in this callback
// Object[] correct = entry.getJBCUpdateValues();
// vals[0] = correct[0];
// vals[1] = correct[1];
// }
}
}
private void storeDataFromJBC(Object key, Object[] vals) {
Entry entry = getLocalEntry(key);
if (vals[0].equals(vals[1])) {
entry.preInvalidate(vals[0]);
}
else {
entry.invalidate(vals[0], vals[1]);
}
}
/**
* Monitors cache events and updates the local cache
*
* @param event
*/
@NodeRemoved
public void nodeRemoved(NodeRemovedEvent event) {
if (event.isOriginLocal() || event.isPre())
return;
Fqn fqn = event.getFqn();
Fqn regFqn = getRegionFqn();
if (fqn.isChildOrEquals(regFqn)) {
if (fqn.size() == regFqn.size()) {
localCache.clear();
}
else {
Object key = fqn.get(regFqn.size());
localCache.remove(key);
}
}
}
/**
* Brings all data from the distributed cache into our local cache.
*/
private void populateLocalCache() {
Set children = CacheHelper.getChildrenNames(getCacheInstance(), getRegionFqn());
for (Object key : children) {
Object[] vals = (Object[]) suspendAndGet(key, null, false);
if (vals != null) {
storeDataFromJBC(key, vals);
}
}
}
private Entry getLocalEntry(Object key) {
Entry entry = new Entry();
Entry oldEntry = (Entry) localCache.putIfAbsent(key, entry);
return (oldEntry == null ? entry : oldEntry);
}
private class Entry {
private Semaphore writeMutex = new Semaphore(1);
private boolean preInvalidated = false;
private Object preInval = null;
private Object current = null;
void acquireJBCWriteMutex() throws InterruptedException {
writeMutex.acquire();
}
void releaseJBCWriteMutex() {
writeMutex.release();
}
synchronized boolean preInvalidate(Object newVal) {
boolean result = false;
if (newVal instanceof Comparable) {
if (current == null || ((Comparable) newVal).compareTo(current) > 0) {
preInval = current = newVal;
preInvalidated = true;
result = true;
}
}
else {
preInval = current = newVal;
result = true;
}
return result;
}
synchronized boolean invalidate(Object newVal, Object preInvalidateValue) {
boolean result = false;
if (current == null) {
// Initial load from JBC
current = newVal;
preInval = preInvalidateValue;
preInvalidated = false;
result = true;
}
else if (preInvalidated) {
if (newVal instanceof Comparable) {
if (safeEquals(preInvalidateValue, this.preInval)
|| ((Comparable) newVal).compareTo(preInval) > 0) {
current = newVal;
preInval = preInvalidateValue;
preInvalidated = false;
result = true;
}
}
else {
current = newVal;
preInval = preInvalidateValue;
result = true;
}
}
else if (newVal instanceof Comparable) {
// See if we had a 2nd invalidation from the same initial
// preinvalidation timestamp. If so, only increment
// if the new current value is an increase
if (safeEquals(preInvalidateValue, this.preInval)
&& ((Comparable) newVal).compareTo(current) > 0) {
current = newVal;
preInval = preInvalidateValue;
result = true;
}
}
return result;
}
synchronized Object getCurrent() {
return current;
}
synchronized Object getPreInval() {
return preInval;
}
synchronized Object[] getJBCUpdateValues() {
return new Object[] {current, preInval};
}
private boolean safeEquals(Object a, Object b) {
return (a == b || (a != null && a.equals(b)));
}
}
}

View File

@ -1,222 +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.jbc.timestamp;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.transaction.Transaction;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.TimestampsRegion;
import org.hibernate.cache.jbc.TransactionalDataRegionAdapter;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
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;
/**
* Defines the behavior of the timestamps cache region for JBossCache 2.x.
*
* TODO Need to define a way to ensure asynchronous replication events
* do not result in timestamps moving backward, while dealing with the fact
* that the normal sequence of UpdateTimestampsCache.preinvalidate() then
* UpdateTimestampsCache.invalidate() will result in 2 calls to put() with
* the latter call having an earlier timestamp.
*
* @author Brian Stansberry
* @version $Revision$
*/
@CacheListener
public class TimestampsRegionImpl extends TransactionalDataRegionAdapter implements TimestampsRegion {
public static final String TYPE = "TS";
private Map localCache = new ConcurrentHashMap();
/**
* Create a new TimestampsRegionImpl.
*
* @param jbcCache The JBC cache instance to use to store the timestamps data
* @param regionName The name of the region (within the JBC cache)
* @param regionPrefix Any region prefix to apply
* @param properties The configuration properties.
*/
public TimestampsRegionImpl(Cache jbcCache, String regionName, String regionPrefix, Properties properties) {
super(jbcCache, regionName, regionPrefix, null);
jbcCache.addCacheListener(this);
populateLocalCache();
}
@Override
protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
return getTypeFirstRegionFqn(regionName, regionPrefix, TYPE);
}
public void evict(Object key) throws CacheException {
ensureRegionRootExists();
// TODO Is this a valid operation on a timestamps cache?
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.removeNode(getCacheInstance(), getRegionFqn(), key, opt);
}
public void evictAll() throws CacheException {
// TODO Is this a valid operation on a timestamps cache?
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 && checkValid()) {
ensureRegionRootExists();
value = suspendAndGet(key, null, false);
if (value != null)
localCache.put(key, value);
}
return value;
}
public void put(Object key, Object value) throws CacheException {
ensureRegionRootExists();
// Don't hold the JBC node lock throughout the tx, as that
// prevents reads and other updates
Transaction tx = suspend();
try {
// TODO Why not use the timestamp in a DataVersion?
Option opt = getNonLockingDataVersionOption(false);
// We ensure ASYNC semantics (JBCACHE-1175)
opt.setForceAsynchronous(true);
CacheHelper.put(getCacheInstance(), getRegionFqn(), key, value, opt);
} catch (Exception e) {
throw new CacheException(e);
} finally {
resume(tx);
}
}
@Override
public void destroy() throws CacheException {
localCache.clear();
getCacheInstance().removeCacheListener(this);
super.destroy();
}
/**
* Monitors cache events and updates the local cache
*
* @param event
*/
@NodeModified
public void nodeModified(NodeModifiedEvent event) {
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));
}
}
}
/**
* Monitors cache events and updates the local cache
*
* @param event
*/
@NodeRemoved
public void nodeRemoved(NodeRemovedEvent 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.remove(key);
}
else if (fqn.equals(regFqn)) {
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() {
Set children = CacheHelper.getChildrenNames(getCacheInstance(), getRegionFqn());
for (Object key : children) {
get(key);
}
}
}

View File

@ -1,491 +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.jbc.util;
import java.util.Collections;
import java.util.Set;
import org.hibernate.cache.CacheException;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.Node;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.Option;
import org.jboss.cache.lock.TimeoutException;
import org.jboss.cache.optimistic.DataVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Helper for dealing with JBossCache {@link Configuration.CacheMode}.
*
* @author Steve Ebersole
* @author Brian Stansberry
*/
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 */
public static final String DUMMY = "dummy";
private static final Logger log = LoggerFactory.getLogger(CacheHelper.class);
/**
* Disallow external instantiation of CacheHelper.
*/
private CacheHelper() {
}
/**
* Is this cache participating in a cluster with invalidation?
*
* @param cache
* The cache to check.
* @return True if the cache is configured for synchronous/asynchronous
* invalidation; false otherwise.
*/
public static boolean isClusteredInvalidation(Cache cache) {
return isClusteredInvalidation(cache.getConfiguration().getCacheMode());
}
/**
* Does this cache mode indicate clustered invalidation?
*
* @param cacheMode
* The cache to check
* @return True if the cache mode is confiogured for
* synchronous/asynchronous invalidation; false otherwise.
*/
public static boolean isClusteredInvalidation(Configuration.CacheMode cacheMode) {
return cacheMode == Configuration.CacheMode.INVALIDATION_ASYNC
|| cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
}
/**
* Is this cache participating in a cluster with replication?
*
* @param cache
* The cache to check.
* @return True if the cache is configured for synchronous/asynchronous
* invalidation; false otherwise.
*/
public static boolean isClusteredReplication(Cache cache) {
return isClusteredReplication(cache.getConfiguration().getCacheMode());
}
/**
* Does this cache mode indicate clustered replication?
*
* @param cacheMode
* The cache to check
* @return True if the cache mode is confiogured for
* synchronous/asynchronous invalidation; false otherwise.
*/
public static boolean isClusteredReplication(Configuration.CacheMode cacheMode) {
return cacheMode == Configuration.CacheMode.REPL_ASYNC || cacheMode == Configuration.CacheMode.REPL_SYNC;
}
public static boolean isSynchronous(Cache cache) {
return isSynchronous(cache.getConfiguration().getCacheMode());
}
public static boolean isSynchronous(Configuration.CacheMode cacheMode) {
return cacheMode == Configuration.CacheMode.REPL_SYNC || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
}
public static Set getChildrenNames(Cache cache, Fqn fqn) {
Node node = cache.getRoot().getChild(fqn);
return (node != null) ? node.getChildrenNames() : Collections.emptySet();
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache <code>get(Fqn, Object)</code>, wrapping any
* exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
*/
public static Object get(Cache cache, Fqn region, Object key) throws CacheException {
try {
return cache.get(new Fqn(region, key), ITEM);
} catch (Exception e) {
throw new CacheException(e);
}
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache <code>get(Fqn, Object)</code>, wrapping any
* exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
*/
public static Object getAllowingTimeout(Cache cache, Fqn region, Object key) throws CacheException {
try {
return cache.get(new Fqn(region, key), ITEM);
}
catch (TimeoutException ignored) {
// ignore it
return null;
}
catch (Exception e) {
throw new CacheException(e);
}
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache <code>put(Object, Object)</code>, wrapping
* any exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
* @param value
* data to store in the cache node
*/
public static void put(Cache cache, Fqn region, Object key, Object value) throws CacheException {
put(cache, region, key, value, null);
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache <code>put(Object, Object)</code>, wrapping
* any exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
* @param value
* data to store in the cache node
* @param option
* invocation Option to set for this invocation. May be
* <code>null</code>.
*/
public static void put(Cache cache, Fqn region, Object key, Object value, Option option) throws CacheException {
try {
setInvocationOption(cache, option);
cache.put(new Fqn(region, key), ITEM, value);
} catch (Exception e) {
throw new CacheException(e);
}
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache <code>put(Object, Object)</code>, ignoring any
* {@link TimeoutException} and wrapping any other exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
* @param value
* data to store in the cache node
* @param option
* invocation Option to set for this invocation. May be
* <code>null</code>.
*/
public static void putAllowingTimeout(Cache cache, Fqn region, Object key, Object value, Option option) throws CacheException {
try {
setInvocationOption(cache, option);
cache.put(new Fqn(region, key), ITEM, value);
}
catch (TimeoutException allowed) {
// ignore it
}
catch (Exception e) {
throw new CacheException(e);
}
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache
* <code>putForExternalRead(Object, Object)</code>, wrapping any
* exception in a {@link CacheException}. Ignores any JBoss Cache
* {@link TimeoutException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
* @param value
* data to store in the cache node
*/
public static boolean putForExternalRead(Cache cache, Fqn region, Object key, Object value) throws CacheException {
return putForExternalRead(cache, region, key, value, null);
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache
* <code>putForExternalRead(Object, Object)</code>, wrapping any
* exception in a {@link CacheException}. Ignores any JBoss Cache
* {@link TimeoutException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
* @param value
* data to store in the cache node
* @param option
* invocation Option to set for this invocation. May be
* <code>null</code>.
*/
public static boolean putForExternalRead(Cache cache, Fqn region, Object key, Object value, Option option)
throws CacheException {
try {
setInvocationOption(cache, option);
cache.putForExternalRead(new Fqn(region, key), ITEM, value);
return true;
} catch (TimeoutException te) {
// ignore!
log.debug("ignoring write lock acquisition failure");
return false;
} catch (Throwable t) {
throw new CacheException(t);
}
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
* exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
*/
public static void remove(Cache cache, Fqn region, Object key) throws CacheException {
remove(cache, region, key, null);
}
/**
* Builds an {@link Fqn} from <code>region</code> and <code>key</code>
* and performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
* exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param key
* specific key to append to the <code>region</code> to form
* the full Fqn
* @param option
* invocation Option to set for this invocation. May be
* <code>null</code>.
*/
public static void remove(Cache cache, Fqn region, Object key, Option option) throws CacheException {
try {
setInvocationOption(cache, option);
cache.removeNode(new Fqn(region, key));
} catch (Exception e) {
throw new CacheException(e);
}
}
/**
* Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
* exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
*/
public static void removeAll(Cache cache, Fqn region) throws CacheException {
removeAll(cache, region, null);
}
/**
* Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
* exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param option
* invocation Option to set for this invocation. May be
* <code>null</code>.
*/
public static void removeAll(Cache cache, Fqn region, Option option) throws CacheException {
try {
setInvocationOption(cache, option);
cache.removeNode(region);
} catch (Exception e) {
throw new CacheException(e);
}
}
/**
* Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
* exception in a {@link CacheException}.
*
* @param cache
* the cache to invoke on
* @param region
* base Fqn for the cache region
* @param option
* invocation Option to set for this invocation. May be
* <code>null</code>.
*/
public static void removeNode(Cache cache, Fqn region, Object key, Option option) throws CacheException {
try {
setInvocationOption(cache, option);
cache.removeNode(new Fqn(region, key));
} catch (Exception e) {
throw new CacheException(e);
}
}
public static Node addNode(Cache cache, Fqn fqn, boolean localOnly, boolean resident, DataVersion version)
throws CacheException {
try {
Option option = null;
if (localOnly || version != null) {
option = new Option();
option.setCacheModeLocal(localOnly);
option.setDataVersion(version);
}
Node root = cache.getRoot();
setInvocationOption(cache, option);
// FIXME hack to work around fact that calling
// Node added = root.addChild( fqn ); doesn't
// properly set the version on the node
Node added = null;
if (version == null) {
added = root.addChild( fqn );
}
else {
cache.put(fqn, DUMMY, DUMMY);
added = root.getChild(fqn);
}
if (resident)
added.setResident(true);
return added;
}
catch (Exception e) {
throw new CacheException(e);
}
}
/**
* Assigns the given Option to the cache's {@link InvocationContext}. Does
* nothing if <code>option</code> is <code>null</code>.
*
* @param cache
* the cache. Cannot be <code>null</code>.
* @param option
* the option. May be <code>null</code>.
*
* @see {@link Cache#getInvocationContext()}
* @see {@link InvocationContext#setOptionOverrides(Option)}
*/
public static void setInvocationOption(Cache cache, Option option) {
if (option != null) {
cache.getInvocationContext().setOptionOverrides(option);
}
}
/**
* Creates an {@link Option} using the given {@link DataVersion} and passes
* it to {@link #setInvocationOption(Cache, Option)}.
*
* @param cache
* the cache to set the Option on. Cannot be <code>null</code>.
* @param version
* the DataVersion to set. Cannot be <code>null</code>.
*/
public static void setDataVersionOption(Cache cache, DataVersion version) {
Option option = new Option();
option.setDataVersion(version);
setInvocationOption(cache, option);
}
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

@ -1,54 +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.jbc.util;
import org.hibernate.cache.CacheException;
import org.jboss.cache.config.Option;
import org.jboss.cache.optimistic.DataVersion;
/**
* Used to signal to a DataVersionAdapter to simply not perform any checks. This
* is currently needed for proper handling of remove() calls for entity cache
* regions (we do not know the version info...).
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class CircumventChecksDataVersion implements DataVersion {
private static final long serialVersionUID = 7996980646166032369L;
public static final DataVersion INSTANCE = new CircumventChecksDataVersion();
public static Option getInvocationOption() {
Option option = new Option();
option.setDataVersion(INSTANCE);
return option;
}
public boolean newerThan(DataVersion dataVersion) {
throw new CacheException("optimistic locking checks should never happen on CircumventChecksDataVersion");
}
}

View File

@ -1,166 +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.jbc.util;
import java.io.IOException;
import java.util.Comparator;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
import org.hibernate.util.CalendarComparator;
import org.hibernate.util.ComparableComparator;
import org.jboss.cache.optimistic.DataVersion;
import org.jboss.cache.optimistic.DefaultDataVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A DataVersionAdapter.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class DataVersionAdapter implements DataVersion {
private static final Logger log = LoggerFactory.getLogger(TransactionalAccess.class);
private static final long serialVersionUID = 5564692336076405571L;
private final Object currentVersion;
private final Object previousVersion;
/**
* Comparator does not extend Serializable and the std impls don't either,
* so we make the field transient to allow special handling
*/
private transient Comparator versionComparator;
private final String sourceIdentifer;
public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator,
String sourceIdentifer) {
this.currentVersion = currentVersion;
this.previousVersion = previousVersion;
this.versionComparator = versionComparator;
this.sourceIdentifer = sourceIdentifer;
log.trace("created " + this);
}
/**
* newerThan() call is dispatched against the DataVersion currently
* associated with the node; the passed dataVersion param is the DataVersion
* associated with the data we are trying to put into the node. <p/> we are
* expected to return true in the case where we (the current node
* DataVersion) are newer that then incoming value. Returning true here
* essentially means that a optimistic lock failure has occured (because
* conversely, the value we are trying to put into the node is "older than"
* the value already there...)
*/
public boolean newerThan(DataVersion dataVersion) {
log.trace("checking [" + this + "] against [" + dataVersion + "]");
if (dataVersion instanceof CircumventChecksDataVersion) {
log.trace("skipping lock checks...");
return false;
} else if (dataVersion instanceof NonLockingDataVersion) {
// can happen because of the multiple ways Cache.remove()
// can be invoked :(
log.trace("skipping lock checks...");
return false;
} else if (dataVersion instanceof DefaultDataVersion) {
// JBC put a version in the node when it created as part of
// some internal operation. We are always newer, but if
// the JBC version is > 1 something odd has happened
if (((DefaultDataVersion) dataVersion).getRawVersion() > 1) {
log.warn("Unexpected comparison to " + dataVersion +
" -- we are " + toString());
}
return true;
}
DataVersionAdapter other = (DataVersionAdapter) dataVersion;
if (other.previousVersion == null) {
log.warn("Unexpected optimistic lock check on inserting data");
// work around the "feature" where tree cache is validating the
// inserted node during the next transaction. no idea...
if (this == dataVersion) {
log.trace("skipping lock checks due to same DV instance");
return false;
}
}
if (currentVersion == null) {
// If the workspace node has null as well, OK; if not we've
// been modified in a non-comparable manner, which we have to
// 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;
}
public String toString() {
return super.toString() + " [current=" + currentVersion + ", previous=" + previousVersion + ", src="
+ sourceIdentifer + "]";
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
// The standard comparator types are not Serializable but are singletons
if (versionComparator instanceof ComparableComparator)
out.writeByte(0);
else if (versionComparator instanceof CalendarComparator)
out.writeByte(1);
else {
out.writeByte(999);
out.writeObject(versionComparator);
}
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
byte comparatorType = in.readByte();
switch (comparatorType) {
case 0:
versionComparator = ComparableComparator.INSTANCE;
break;
case 1:
versionComparator = CalendarComparator.INSTANCE;
break;
default:
versionComparator = (Comparator) in.readObject();
}
}
}

View File

@ -1,65 +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.jbc.util;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
import org.jboss.cache.config.Option;
import org.jboss.cache.optimistic.DataVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link DataVersion} used in regions where no locking should ever occur. This
* includes query-caches, update-timestamps caches, collection caches, and
* entity caches where the entity is not versioned.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class NonLockingDataVersion implements DataVersion {
private static final Logger log = LoggerFactory.getLogger(TransactionalAccess.class);
private static final long serialVersionUID = 7050722490368630553L;
public static final DataVersion INSTANCE = new NonLockingDataVersion();
public static Option getInvocationOption() {
Option option = new Option();
option.setDataVersion(INSTANCE);
return option;
}
public boolean newerThan(DataVersion dataVersion) {
// if (dataVersion instanceof DefaultDataVersion) {
// log.info("unexpectedly validating against a DefaultDataVersion", new Exception("Just a stack trace"));
// return true;
// }
// else {
log.trace("non locking lock check...");
return false;
// }
}
}

View File

@ -1,69 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, 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.jbc2;
import java.util.Properties;
import org.hibernate.cache.jbc.CacheInstanceManager;
/**
* Deprecated version of superclass maintained solely for forwards
* compatibility.
*
* @deprecated use {@link org.hibernate.cache.jbc.JBossCacheRegionFactory}
*
* @author Steve Ebersole
* @author Brian Stansberry
*/
@Deprecated
public class JBossCacheRegionFactory extends org.hibernate.cache.jbc.JBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public JBossCacheRegionFactory(Properties props) {
super(props);
}
/**
* Create a new JBossCacheRegionFactory.
*/
public JBossCacheRegionFactory() {
super();
}
/**
* Create a new JBossCacheRegionFactory that uses the provided
* {@link CacheInstanceManager}.
*
* @param cacheInstanceManager The contract for how we get JBC cache instances.
*/
public JBossCacheRegionFactory(CacheInstanceManager cacheInstanceManager) {
super(cacheInstanceManager);
}
}

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, 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.jbc2;
import java.util.Properties;
/**
* Deprecated version of superclass maintained solely for forwards
* compatibility.
*
* @deprecated use {@link org.hibernate.cache.jbc.JndiMultiplexedJBossCacheRegionFactory}
*
* @author Brian Stansberry
* @version $Revision$
*/
@Deprecated
public class JndiMultiplexedJBossCacheRegionFactory extends org.hibernate.cache.jbc.JndiMultiplexedJBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public JndiMultiplexedJBossCacheRegionFactory(Properties props) {
super(props);
}
/**
* Create a new MultiplexedJBossCacheRegionFactory.
*
*/
public JndiMultiplexedJBossCacheRegionFactory() {
super();
}
}

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, 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.jbc2;
import java.util.Properties;
/**
* Deprecated version of superclass maintained solely for forwards
* compatibility.
*
* @deprecated use {@link org.hibernate.cache.jbc.JndiSharedJBossCacheRegionFactory}
*
* @author Brian Stansberry
* @version $Revision$
*/
@Deprecated
public class JndiSharedJBossCacheRegionFactory extends org.hibernate.cache.jbc.JndiSharedJBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public JndiSharedJBossCacheRegionFactory(Properties props) {
super(props);
}
/**
* Create a new JndiSharedJBossCacheRegionFactory.
*
*/
public JndiSharedJBossCacheRegionFactory() {
super();
}
}

View File

@ -1,57 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, 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.jbc2;
import java.util.Properties;
/**
* Deprecated version of superclass maintained solely for forwards
* compatibility.
*
* @deprecated use {@link org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory}
*
* @author Brian Stansberry
* @version $Revision$
*/
public class MultiplexedJBossCacheRegionFactory extends org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public MultiplexedJBossCacheRegionFactory(Properties props) {
super(props);
}
/**
* Create a new MultiplexedJBossCacheRegionFactory.
*
*/
public MultiplexedJBossCacheRegionFactory() {
super();
}
}

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, 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.jbc2;
import java.util.Properties;
/**
* Deprecated version of superclass maintained solely for forwards
* compatibility.
*
* @deprecated use {@link org.hibernate.cache.jbc.SharedJBossCacheRegionFactory}
*
* @author Brian Stansberry
* @version $Revision$
*/
@Deprecated
public class SharedJBossCacheRegionFactory extends org.hibernate.cache.jbc.SharedJBossCacheRegionFactory {
/**
* FIXME Per the RegionFactory class Javadoc, this constructor version
* should not be necessary.
*
* @param props The configuration properties
*/
public SharedJBossCacheRegionFactory(Properties props) {
super(props);
}
/**
* Create a new SharedJBossCacheRegionFactory.
*
*/
public SharedJBossCacheRegionFactory() {
super();
}
}

View File

@ -1,327 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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
-->
<!--
Sample file that defines a number of stacks, used by the multiplexer
Author: Bela Ban
Version: $Id$
-->
<protocol_stacks>
<stack name="udp"
description="Default: IP multicast based stack, with flow control and message bundling">
<config>
<UDP
mcast_addr="${jgroups.udp.mcast_addr:228.10.10.10}"
mcast_port="${jgroups.udp.mcast_port:45588}"
tos="8"
ucast_recv_buf_size="20000000"
ucast_send_buf_size="640000"
mcast_recv_buf_size="25000000"
mcast_send_buf_size="640000"
loopback="true"
discard_incompatible_packets="true"
max_bundle_size="64000"
max_bundle_timeout="30"
use_incoming_packet_handler="true"
ip_ttl="${jgroups.udp.ip_ttl:2}"
enable_bundling="${jgroup.udp.enable_bundling:true}"
use_concurrent_stack="true"
thread_pool.enabled="true"
thread_pool.min_threads="1"
thread_pool.max_threads="25"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="false"
thread_pool.queue_max_size="100"
thread_pool.rejection_policy="Run"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="1"
oob_thread_pool.max_threads="8"
oob_thread_pool.keep_alive_time="5000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.queue_max_size="100"
oob_thread_pool.rejection_policy="Run"/>
<PING timeout="${jgroups.ping.timeout:2000}"
num_initial_members="${jgroups.ping.num_initial_members:3}"/>
<MERGE2 max_interval="100000"
min_interval="20000"/>
<FD_SOCK/>
<FD timeout="10000" max_tries="5" shun="true"/>
<VERIFY_SUSPECT timeout="1500" />
<pbcast.NAKACK
use_mcast_xmit="false" gc_lag="0"
retransmit_timeout="300,600,1200,2400,4800"
discard_delivered_msgs="false"/>
<UNICAST timeout="300,600,1200,2400,3600"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="400000"/>
<pbcast.GMS print_local_addr="true"
join_timeout="3000"
shun="false"
view_bundling="true"
view_ack_collection_timeout="5000"/>
<FC max_credits="2000000"
min_threshold="0.10"/>
<FRAG2 frag_size="60000" />
<pbcast.STREAMING_STATE_TRANSFER/>
<!-- <pbcast.STATE_TRANSFER/> -->
<pbcast.FLUSH timeout="0"/>
</config>
</stack>
<stack name="udp-sync"
description="IP multicast based stack, without flow control and without message bundling. This should be used
instead of udp if (1) synchronous calls are used and (2) the message volume (rate and size)
is not that large. Don't use this configuration if you send messages at a high sustained rate, or you might
run out of memory">
<config>
<UDP
mcast_addr="${jgroups.udp.mcast_addr:229.10.10.10}"
mcast_port="${jgroups.udp.mcast_port:45599}"
tos="8"
ucast_recv_buf_size="20000000"
ucast_send_buf_size="640000"
mcast_recv_buf_size="25000000"
mcast_send_buf_size="640000"
loopback="true"
discard_incompatible_packets="true"
max_bundle_size="64000"
max_bundle_timeout="30"
use_incoming_packet_handler="true"
ip_ttl="${jgroups.udp.ip_ttl:2}"
enable_bundling="${jgroup.udp.enable_bundling:true}"
use_concurrent_stack="true"
thread_pool.enabled="true"
thread_pool.min_threads="1"
thread_pool.max_threads="25"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="false"
thread_pool.queue_max_size="100"
thread_pool.rejection_policy="Run"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="1"
oob_thread_pool.max_threads="8"
oob_thread_pool.keep_alive_time="5000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.queue_max_size="100"
oob_thread_pool.rejection_policy="Run"/>
<PING timeout="${jgroups.ping.timeout:2000}"
num_initial_members="${jgroups.ping.num_initial_members:3}"/>
<MERGE2 max_interval="100000"
min_interval="20000"/>
<FD_SOCK/>
<FD timeout="10000" max_tries="5" shun="true"/>
<VERIFY_SUSPECT timeout="1500" />
<pbcast.NAKACK
use_mcast_xmit="false" gc_lag="0"
retransmit_timeout="300,600,1200,2400,4800"
discard_delivered_msgs="false"/>
<UNICAST timeout="300,600,1200,2400,3600"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="400000"/>
<pbcast.GMS print_local_addr="true"
join_timeout="3000"
shun="false"
view_bundling="true"/>
<FRAG2 frag_size="60000" />
<pbcast.STREAMING_STATE_TRANSFER/>
<!-- <pbcast.STATE_TRANSFER/> -->
<pbcast.FLUSH timeout="0"/>
</config>
</stack>
<stack name="tcp"
description="TCP based stack, with flow control and message bundling. This is usually used when IP
multicasting cannot be used in a network, e.g. because it is disabled (routers discard multicast).
Note that TCP.bind_addr and TCPPING.initial_hosts should be set, possibly via system properties, e.g.
-Djgroups.bind_addr=192.168.5.2 and -Djgroups.tcpping.initial_hosts=192.168.5.2[7800]">
<config>
<TCP start_port="7800"
loopback="true"
recv_buf_size="20000000"
send_buf_size="640000"
discard_incompatible_packets="true"
max_bundle_size="64000"
max_bundle_timeout="30"
use_incoming_packet_handler="true"
enable_bundling="true"
use_send_queues="false"
sock_conn_timeout="300"
skip_suspected_members="true"
use_concurrent_stack="true"
thread_pool.enabled="true"
thread_pool.min_threads="1"
thread_pool.max_threads="25"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="false"
thread_pool.queue_max_size="100"
thread_pool.rejection_policy="run"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="1"
oob_thread_pool.max_threads="8"
oob_thread_pool.keep_alive_time="5000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.queue_max_size="100"
oob_thread_pool.rejection_policy="run"/>
<TCPPING timeout="3000"
initial_hosts="${jgroups.tcpping.initial_hosts:localhost[7800],localhost[7801]}"
port_range="1"
num_initial_members="3"/>
<MERGE2 max_interval="100000"
min_interval="20000"/>
<FD_SOCK/>
<FD timeout="10000" max_tries="5" shun="true"/>
<VERIFY_SUSPECT timeout="1500" />
<pbcast.NAKACK
use_mcast_xmit="false" gc_lag="0"
retransmit_timeout="300,600,1200,2400,4800"
discard_delivered_msgs="false"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="400000"/>
<pbcast.GMS print_local_addr="true"
join_timeout="3000"
shun="false"
view_bundling="true"/>
<FC max_credits="2000000"
min_threshold="0.10"/>
<FRAG2 frag_size="60000" />
<pbcast.STREAMING_STATE_TRANSFER/>
<!-- <pbcast.STATE_TRANSFER/> -->
<pbcast.FLUSH timeout="0"/>
</config>
</stack>
<stack name="tcp-sync"
description="TCP based stack, without flow control and without message bundling. This is usually used when IP
multicasting cannot be used in a network, e.g. because it is disabled (routers discard multicast). This
configuration should be used instead of tcp when (1) synchronous calls are used and (2) the message volume
(rate and size) is not that large">
<config>
<TCP start_port="7900"
loopback="true"
recv_buf_size="20000000"
send_buf_size="640000"
discard_incompatible_packets="true"
max_bundle_size="64000"
max_bundle_timeout="30"
use_incoming_packet_handler="true"
enable_bundling="true"
use_send_queues="false"
sock_conn_timeout="300"
skip_suspected_members="true"
thread_pool.enabled="true"
thread_pool.min_threads="1"
thread_pool.max_threads="25"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="false"
thread_pool.queue_max_size="100"
thread_pool.rejection_policy="run"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="1"
oob_thread_pool.max_threads="8"
oob_thread_pool.keep_alive_time="5000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.queue_max_size="100"
oob_thread_pool.rejection_policy="run"/>
<TCPPING timeout="3000"
initial_hosts="${jgroups.tcpping.initial_hosts:localhost[7900],localhost[7901]}"
port_range="1"
num_initial_members="3"/>
<MERGE2 max_interval="100000"
min_interval="20000"/>
<FD_SOCK/>
<FD timeout="10000" max_tries="5" shun="true"/>
<VERIFY_SUSPECT timeout="1500" />
<pbcast.NAKACK
use_mcast_xmit="false" gc_lag="0"
retransmit_timeout="300,600,1200,2400,4800"
discard_delivered_msgs="false"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="400000"/>
<pbcast.GMS print_local_addr="true"
join_timeout="3000"
shun="false"
view_bundling="true"/>
<pbcast.STREAMING_STATE_TRANSFER/>
<!-- <pbcast.STATE_TRANSFER/> -->
<pbcast.FLUSH timeout="0"/>
</config>
</stack>
<stack name="tunnel"
description="Used with a GossipRouter">
<config>
<TUNNEL router_port="12001" router_host="127.0.0.1"/>
<PING timeout="2000"
num_initial_members="3"
gossip_refresh="10000"
gossip_host="127.0.0.1"
gossip_port="12001"/>
<MERGE2 max_interval="20000"
min_interval="5000"/>
<FD timeout="2000" max_tries="3" shun="true"/>
<VERIFY_SUSPECT timeout="1500" />
<pbcast.NAKACK
use_mcast_xmit="false" gc_lag="0"
retransmit_timeout="300,600,1200,2400,4800"
discard_delivered_msgs="false"/>
<UNICAST timeout="300,600,1200,2400,3600"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="5000"
max_bytes="400000"/>
<pbcast.GMS print_local_addr="true"
join_timeout="3000"
shun="false"
view_bundling="true"
view_ack_collection_timeout="5000"/>
<FC max_credits="2000000"
min_threshold="0.10"/>
<FRAG2 frag_size="60000" />
<!-- <pbcast.STREAMING_STATE_TRANSFER/> -->
<pbcast.STATE_TRANSFER/>
<pbcast.FLUSH timeout="0"/>
</config>
</stack>
</protocol_stacks>

View File

@ -1,147 +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.test.cache.jbc;
import java.util.Properties;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.TransactionalDataRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.SharedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc.builder.SharedCacheInstanceManager;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.test.util.CacheTestUtil;
/**
* Base class for tests of EntityRegion and CollectionRegion implementations.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractEntityCollectionRegionTestCase extends AbstractRegionImplTestCase {
/**
* Create a new EntityCollectionRegionTestCaseBase.
*
* @param name
*/
public AbstractEntityCollectionRegionTestCase(String name) {
super(name);
}
/**
* Create a Region backed by an OPTIMISTIC locking JBoss Cache, and then
* ensure that it handles calls to buildAccessStrategy as expected when
* all the various {@link AccessType}s are passed as arguments.
*/
public void testSupportedAccessTypesOptimistic() throws Exception {
supportedAccessTypeTest(true);
}
/**
* Creates a Region backed by an PESSIMISTIC locking JBoss Cache, and then
* ensures that it handles calls to buildAccessStrategy as expected when
* all the various {@link AccessType}s are passed as arguments.
*/
public void testSupportedAccessTypesPessimistic() throws Exception {
supportedAccessTypeTest(false);
}
private void supportedAccessTypeTest(boolean optimistic) throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, true, false);
String entityCfg = optimistic ? "optimistic-entity" : "pessimistic-entity";
cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, entityCfg);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
supportedAccessTypeTest(regionFactory, cfg.getProperties());
}
/**
* Creates a Region using the given factory, and then ensure that it
* handles calls to buildAccessStrategy as expected when all the
* various {@link AccessType}s are passed as arguments.
*/
protected abstract void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties);
/**
* Test that the Region properly implements
* {@link TransactionalDataRegion#isTransactionAware()}.
*
* @throws Exception
*/
public void testIsTransactionAware() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
assertTrue("Region is transaction-aware", region.isTransactionAware());
CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
// Make it non-transactional
cfg.getProperties().remove(Environment.TRANSACTION_MANAGER_STRATEGY);
regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
assertFalse("Region is not transaction-aware", region.isTransactionAware());
CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
}
public void testGetCacheDataDescription() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
CacheDataDescription cdd = region.getCacheDataDescription();
assertNotNull(cdd);
CacheDataDescription expected = getCacheDataDescription();
assertEquals(expected.isMutable(), cdd.isMutable());
assertEquals(expected.isVersioned(), cdd.isVersioned());
assertEquals(expected.getVersionComparator(), cdd.getVersionComparator());
}
}

View File

@ -1,259 +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.test.cache.jbc;
import java.util.Iterator;
import org.hibernate.cache.GeneralDataRegion;
import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.Region;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cache.jbc.util.NonLockingDataVersion;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.util.CacheTestUtil;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.transaction.BatchModeTransactionManager;
/**
* Base class for tests of QueryResultsRegion and TimestampsRegion.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionImplTestCase {
protected static final String KEY = "Key";
protected static final String VALUE1 = "value1";
protected static final String VALUE2 = "value2";
public AbstractGeneralDataRegionTestCase(String name) {
super(name);
}
@Override
protected void putInRegion(Region region, Object key, Object value) {
((GeneralDataRegion) region).put(key, value);
}
@Override
protected void removeFromRegion(Region region, Object key) {
((GeneralDataRegion) region).evict(key);
}
/**
* Test method for {@link QueryResultsRegion#evict(java.lang.Object)}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the CollectionRegionAccessStrategy API.
*/
public void testEvictOptimistic() throws Exception {
evictOrRemoveTest("optimistic-shared");
}
/**
* Test method for {@link QueryResultsRegion#evict(java.lang.Object)}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the CollectionRegionAccessStrategy API.
*/
public void testEvictPessimistic() throws Exception {
evictOrRemoveTest("pessimistic-shared");
}
private void evictOrRemoveTest(String configName) throws Exception {
Configuration cfg = createConfiguration(configName);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
Cache localCache = getJBossCache(regionFactory);
boolean invalidation = CacheHelper.isClusteredInvalidation(localCache);
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory, getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
cfg = createConfiguration(configName);
regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory, getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
assertNull("local is clean", localRegion.get(KEY));
assertNull("remote is clean", remoteRegion.get(KEY));
localRegion.put(KEY, VALUE1);
assertEquals(VALUE1, localRegion.get(KEY));
// allow async propagation
sleep(250);
Object expected = invalidation ? null : VALUE1;
assertEquals(expected, remoteRegion.get(KEY));
localRegion.evict(KEY);
assertEquals(null, localRegion.get(KEY));
assertEquals(null, remoteRegion.get(KEY));
}
protected abstract String getStandardRegionName(String regionPrefix);
/**
* Test method for {@link QueryResultsRegion#evictAll()}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the CollectionRegionAccessStrategy API.
*/
public void testEvictAllOptimistic() throws Exception {
evictOrRemoveAllTest("optimistic-shared");
}
/**
* Test method for {@link QueryResultsRegion#evictAll()}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the CollectionRegionAccessStrategy API.
*/
public void testEvictAllPessimistic() throws Exception {
evictOrRemoveAllTest("pessimistic-shared");
}
private void evictOrRemoveAllTest(String configName) throws Exception {
Configuration cfg = createConfiguration(configName);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
Cache localCache = getJBossCache(regionFactory);
boolean optimistic = "OPTIMISTIC".equals(localCache.getConfiguration().getNodeLockingSchemeString());
boolean invalidation = CacheHelper.isClusteredInvalidation(localCache);
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory, getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
cfg = createConfiguration(configName);
regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
Cache remoteCache = getJBossCache(regionFactory);
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory, getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
Fqn regionFqn = getRegionFqn(getStandardRegionName(REGION_PREFIX), REGION_PREFIX);
Node regionRoot = localCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertEquals("No children in " + regionRoot, 0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (optimistic) {
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (optimistic) {
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
assertNull("local is clean", localRegion.get(KEY));
assertNull("remote is clean", remoteRegion.get(KEY));
localRegion.put(KEY, VALUE1);
assertEquals(VALUE1, localRegion.get(KEY));
// Allow async propagation
sleep(250);
remoteRegion.put(KEY, VALUE1);
assertEquals(VALUE1, remoteRegion.get(KEY));
// Allow async propagation
sleep(250);
if (optimistic) {
regionRoot = localCache.getRoot().getChild(regionFqn);
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
localRegion.evictAll();
// This should re-establish the region root node
assertNull(localRegion.get(KEY));
regionRoot = localCache.getRoot().getChild(regionFqn);
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, remoteRegion.get(KEY));
regionRoot = remoteCache.getRoot().getChild(regionFqn);
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));
}
private void checkNodeIsEmpty(Node node) {
assertEquals("Known issue JBCACHE-1200. node " + node.getFqn() + " should not have keys", 0, node.getKeys().size());
for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
checkNodeIsEmpty((Node) it.next());
}
}
protected Configuration createConfiguration(String configName) {
Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, false, true);
cfg.setProperty(MultiplexingCacheInstanceManager.QUERY_CACHE_RESOURCE_PROP, configName);
cfg.setProperty(MultiplexingCacheInstanceManager.TIMESTAMP_CACHE_RESOURCE_PROP, configName);
return cfg;
}
protected void rollback() {
try {
BatchModeTransactionManager.getInstance().rollback();
}
catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}

View File

@ -1,115 +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.test.cache.jbc;
import java.util.Set;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.testing.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;
/**
* Base class for all non-functional tests of JBoss Cache integration.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractJBossCacheTestCase extends UnitTestCase {
public static final String REGION_PREFIX = "test";
private CacheTestSupport testSupport;
protected final Logger log = LoggerFactory.getLogger(getClass());
public AbstractJBossCacheTestCase(String name) {
super(name);
testSupport = new CacheTestSupport(log);
}
@Override
protected void setUp() throws Exception {
super.setUp();
testSupport.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
testSupport.tearDown();
}
protected void registerCache(Cache cache) {
testSupport.registerCache(cache);
}
protected void unregisterCache(Cache cache) {
testSupport.unregisterCache(cache);
}
protected void registerFactory(RegionFactory factory) {
testSupport.registerFactory(factory);
}
protected void unregisterFactory(RegionFactory factory) {
testSupport.unregisterFactory(factory);
}
protected CacheTestSupport getCacheTestSupport() {
return testSupport;
}
protected void sleep(long ms) {
try {
Thread.sleep(ms);
}
catch (InterruptedException e) {
log.warn("Interrupted during sleep", e);
}
}
protected void avoidConcurrentFlush() {
testSupport.avoidConcurrentFlush();
}
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

@ -1,160 +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.test.cache.jbc;
import java.util.Map;
import java.util.Properties;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.Region;
import org.hibernate.cache.impl.CacheDataDescriptionImpl;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.SharedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.SharedCacheInstanceManager;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.util.CacheTestUtil;
import org.hibernate.util.ComparableComparator;
import org.jboss.cache.Cache;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.config.Option;
import org.jgroups.JChannelFactory;
/**
* Base class for tests of Region implementations.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractRegionImplTestCase extends AbstractJBossCacheTestCase {
/**
* Create a new RegionImplTestCaseBase.
*
* @param name
*/
public AbstractRegionImplTestCase(String name) {
super(name);
}
/**
* Tests proper handling of region initialization and destruction.
*
* @throws Exception
*/
public void testActivationDeactivation() throws Exception {
// Set up a cache to monitor affects of starting the region
Cache remoteCache = DefaultCacheFactory.getInstance().createCache(SharedCacheInstanceManager.DEFAULT_CACHE_RESOURCE, false);
// This test assumes replication; verify that's correct
assertEquals("Cache is REPL_SYNC", "REPL_SYNC", remoteCache.getConfiguration().getCacheModeString());
JChannelFactory channelFactory = new JChannelFactory();
channelFactory.setMultiplexerConfig(SharedCacheInstanceManager.DEF_JGROUPS_RESOURCE);
remoteCache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(channelFactory);
remoteCache.start();
// Make sure we stop the remoteCache
registerCache(remoteCache);
Fqn regionFqn = getRegionFqn("test/test", "test");
assertNull("No region node", remoteCache.getRoot().getChild( regionFqn ));
Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, true);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
Region region = createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
Cache localCache = getJBossCache( regionFactory );
// This test assumes replication; verify that's correct
assertEquals("Cache is REPL_SYNC", "REPL_SYNC", localCache.getConfiguration().getCacheModeString());
// Region creation should not have affected remoteCache
assertNull("No region node", remoteCache.getRoot().getChild( regionFqn ));
Node regionRoot = localCache.getRoot().getChild( regionFqn );
assertTrue("Has a node at " + regionFqn, regionRoot != null );
assertTrue(regionFqn + " is resident", regionRoot.isResident() );
// Confirm region destroy does not affect remote cache
Option option = new Option();
option.setCacheModeLocal(true);
remoteCache.getInvocationContext().setOptionOverrides(option);
remoteCache.put(regionFqn, "test", "test");
assertEquals("Put succeeded", "test", remoteCache.get(regionFqn, "test"));
assertNull("Put was local", localCache.get(regionFqn, "test"));
region.destroy();
assertEquals("Remote cache unchanged", "test", remoteCache.get(regionFqn, "test"));
assertNull("No region node", localCache.getRoot().getChild( regionFqn ));
}
public void testToMap() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, true);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
Region region = createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
Map map = region.toMap();
assertNotNull(map);
assertEquals(0, map.size());
putInRegion(region, "key1", "value1");
putInRegion(region, "key2", "value2");
map = region.toMap();
assertNotNull(map);
assertEquals(2, map.size());
assertEquals("value1", map.get("key1"));
assertEquals("value2", map.get("key2"));
removeFromRegion(region, "key1");
map = region.toMap();
assertNotNull(map);
assertEquals(1, map.size());
assertEquals("value2", map.get("key2"));
}
protected abstract Cache getJBossCache(JBossCacheRegionFactory regionFactory);
protected abstract Fqn getRegionFqn(String regionName, String regionPrefix);
protected abstract Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd);
protected abstract void putInRegion(Region region, Object key, Object value);
protected abstract void removeFromRegion(Region region, Object key);
protected CacheDataDescription getCacheDataDescription() {
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
}
}

View File

@ -1,177 +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.test.cache.jbc;
import junit.framework.TestCase;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.SharedCacheInstanceManager;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Settings;
import org.hibernate.test.util.CacheTestSupport;
import org.hibernate.test.util.CacheTestUtil;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.Option;
import org.jboss.cache.optimistic.DataVersion;
import org.jboss.cache.transaction.BatchModeTransactionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Tests that JBC itself functions as expected in certain areas where there
* may have been problems in the past. Basically tests JBC itself, not the
* Hibernate/JBC integration.
*
* TODO if the equivalent tests are not in the JBC testsuite, add them.
*
* @author Brian Stansberry
*/
public class JBossCacheComplianceTest extends TestCase {
private CacheTestSupport testSupport;
protected final Logger log = LoggerFactory.getLogger(getClass());
public JBossCacheComplianceTest(String x) {
super(x);
testSupport = new CacheTestSupport(log);
}
protected String getConfigResourceKey() {
return SharedCacheInstanceManager.CACHE_RESOURCE_PROP;
}
protected String getConfigResourceLocation() {
return "org/hibernate/test/cache/jbc/functional/optimistic-treecache.xml";
}
protected Class<? extends RegionFactory> getCacheRegionFactory() {
return JBossCacheRegionFactory.class;
}
@Override
protected void setUp() throws Exception {
super.setUp();
testSupport.setUp();
}
@Override
protected void tearDown() throws Exception {
testSupport.tearDown();
super.tearDown();
}
@SuppressWarnings("unchecked")
public void testCacheLevelStaleWritesFail() throws Throwable {
Configuration cfg = CacheTestUtil.buildConfiguration("", MultiplexedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(getConfigResourceKey(), getConfigResourceLocation());
Settings settings = cfg.buildSettings();
Fqn<String> fqn = Fqn.fromString("/whatever");
JBossCacheRegionFactory regionFactory = (JBossCacheRegionFactory) settings.getRegionFactory();
regionFactory.start(settings, cfg.getProperties());
// Make sure we clean up when done
testSupport.registerFactory(regionFactory);
Cache<Object, Object> treeCache = regionFactory.getCacheInstanceManager().getEntityCacheInstance();
// Make sure this is an OPTIMISTIC cache
assertEquals("Cache is OPTIMISTIC", "OPTIMISTIC", treeCache.getConfiguration().getNodeLockingSchemeString());
Long long1 = new Long(1);
Long long2 = new Long(2);
try {
System.out.println("****************************************************************");
BatchModeTransactionManager.getInstance().begin();
CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(1));
treeCache.put(fqn, "ITEM", long1);
BatchModeTransactionManager.getInstance().commit();
System.out.println("****************************************************************");
BatchModeTransactionManager.getInstance().begin();
CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(2));
treeCache.put(fqn, "ITEM", long2);
BatchModeTransactionManager.getInstance().commit();
try {
System.out.println("****************************************************************");
BatchModeTransactionManager.getInstance().begin();
CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(1));
treeCache.put(fqn, "ITEM", long1);
BatchModeTransactionManager.getInstance().commit();
fail("stale write allowed");
} catch (Throwable ignore) {
// expected behavior
try {
BatchModeTransactionManager.getInstance().rollback();
}
catch (IllegalStateException ignored) {
// tx is already cleared
}
}
Long current = (Long) treeCache.get(fqn, "ITEM");
assertEquals("unexpected current value", 2, current.longValue());
} finally {
try {
treeCache.remove(fqn, "ITEM");
} catch (Throwable ignore) {
}
}
}
private static class ManualDataVersion implements DataVersion {
/** The serialVersionUID */
private static final long serialVersionUID = 1L;
private final int version;
public ManualDataVersion(int version) {
this.version = version;
}
public boolean newerThan(DataVersion dataVersion) {
return this.version > ((ManualDataVersion) dataVersion).version;
}
public static Option gen(int version) {
ManualDataVersion mdv = new ManualDataVersion(version);
Option option = new Option();
option.setDataVersion(mdv);
return option;
}
}
}

View File

@ -1,93 +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.test.cache.jbc;
import java.util.Properties;
import org.hibernate.cache.jbc.CacheInstanceManager;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc.builder.SharedCacheInstanceManager;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Settings;
import org.hibernate.test.util.CacheTestUtil;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheStatus;
/**
* A JBossCacheRegionFactoryTestCase.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class JBossCacheRegionFactoryTestCase extends AbstractJBossCacheTestCase {
/**
* Create a new JBossCacheRegionFactoryTestCase.
*
* @param name
*/
public JBossCacheRegionFactoryTestCase(String name) {
super(name);
}
public void testDefaultConfig() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("", JBossCacheRegionFactory.class, true, true);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
assertTrue("Correct default CacheInstanceManager type", mgr instanceof SharedCacheInstanceManager);
Cache cache = mgr.getEntityCacheInstance();
assertTrue("entity cache exists", cache != null);
assertEquals("Used correct config", "TestSharedCache", cache.getConfiguration().getClusterName());
assertEquals("Cache started", CacheStatus.STARTED, cache.getCacheStatus());
CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
assertEquals("Cache destroyed", CacheStatus.DESTROYED, cache.getCacheStatus());
}
public void testInjectedCacheInstanceManager() {
Configuration cfg = CacheTestUtil.buildConfiguration("", JBossCacheRegionFactory.class, true, true);
CacheInstanceManager cim = new MultiplexingCacheInstanceManager();
JBossCacheRegionFactory regionFactory = new JBossCacheRegionFactory(cim);
Settings settings = cfg.buildSettings();
Properties properties = cfg.getProperties();
regionFactory.start(settings, properties);
// Ensure we clean up
registerFactory(regionFactory);
assertEquals("Used injected CacheInstanceManager", cim, regionFactory.getCacheInstanceManager());
CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
}
}

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
*
* 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, v. 2.1. This program is distributed in the
* hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
* distribution; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Red Hat Author(s): Brian Stansberry
*/
package org.hibernate.test.cache.jbc;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.hibernate.test.util.CacheManagerTestSetup;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheManager;
/**
* Tests the validity of the JBC configs in jbc2-configs.xml.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class JbcConfigsXmlValidityTestCase extends AbstractJBossCacheTestCase
{
private static final AtomicReference<CacheManager> cacheManagerRef = new AtomicReference<CacheManager>();
private static final Set<String> stdConfigs = new HashSet<String>();
static
{
stdConfigs.add("optimistic-entity");
stdConfigs.add("pessimistic-entity");
stdConfigs.add("pessimistic-entity-repeatable");
stdConfigs.add("optimistic-shared");
stdConfigs.add("pessimistic-shared");
stdConfigs.add("pessimistic-shared-repeatable");
stdConfigs.add("local-query");
stdConfigs.add("replicated-query");
stdConfigs.add("timestamps-cache");
}
private CacheManager mgr;
private String cacheName;
private Cache cache;
/**
* Create a new JbcConfigsXmlValidityTestCase.
*
* @param name
*/
public JbcConfigsXmlValidityTestCase(String name)
{
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = new TestSuite(JbcConfigsXmlValidityTestCase.class);
return new CacheManagerTestSetup(suite, cacheManagerRef);
}
@Override
protected void setUp() throws Exception
{
super.setUp();
this.mgr = cacheManagerRef.get();
}
@Override
protected void tearDown() throws Exception
{
super.tearDown();
if (cache != null)
{
try
{
mgr.releaseCache(this.cacheName);
}
catch (Exception ignored) {}
cache = null;
}
mgr = null;
}
public void testOptimisticEntity() throws Exception
{
stdConfigTest("optimistic-entity");
}
public void testPessimisticEntity() throws Exception
{
stdConfigTest("pessimistic-entity");
}
public void testPessimisticEntityRepeatable() throws Exception
{
stdConfigTest("pessimistic-entity-repeatable");
}
public void testOptimisticShared() throws Exception
{
stdConfigTest("optimistic-shared");
}
public void testPessimisticShared() throws Exception
{
stdConfigTest("pessimistic-shared");
}
public void testPessimisticSharedRepeatable() throws Exception
{
stdConfigTest("pessimistic-shared-repeatable");
}
public void testLocalQuery() throws Exception
{
stdConfigTest("local-query");
}
public void testReplicatedQuery() throws Exception
{
stdConfigTest("replicated-query");
}
public void testTimestampsCache() throws Exception
{
stdConfigTest("timestamps-cache");
}
public void testAdditionalConfigs() throws Exception
{
Set<String> names = new HashSet<String>(this.mgr.getConfigurationNames());
names.removeAll(stdConfigs);
for (String name : names)
{
configTest(name);
}
}
private void stdConfigTest(String configName) throws Exception
{
assertTrue(this.mgr.getConfigurationNames().contains(configName));
configTest(configName);
}
private void configTest(String configName) throws Exception
{
this.cacheName = configName;
this.cache = mgr.getCache(configName, true);
this.cache.start();
this.mgr.releaseCache(this.cacheName);
this.cache = null;
}
}

View File

@ -1,586 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, 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 Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.cache.jbc.access;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import junit.framework.TestCase;
import org.hibernate.cache.jbc.access.PutFromLoadValidator;
import org.hibernate.test.cache.jbc.functional.util.DualNodeJtaTransactionManagerImpl;
/**
* Tests of {@link PutFromLoadValidator}.
*
* @author Brian Stansberry
*
* @version $Revision: $
*/
public class PutFromLoadValidatorUnitTestCase extends TestCase {
private Object KEY1 = "KEY1";
private TransactionManager tm;
public PutFromLoadValidatorUnitTestCase(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
tm = DualNodeJtaTransactionManagerImpl.getInstance("test");
}
@Override
protected void tearDown() throws Exception {
try {
super.tearDown();
} finally {
tm = null;
try {
DualNodeJtaTransactionManagerImpl.cleanupTransactions();
} finally {
DualNodeJtaTransactionManagerImpl.cleanupTransactionManagers();
}
}
}
public void testNakedPut() throws Exception {
nakedPutTest(false);
}
public void testNakedPutTransactional() throws Exception {
nakedPutTest(true);
}
private void nakedPutTest(boolean transactional) throws Exception {
PutFromLoadValidator testee = new PutFromLoadValidator(
transactional ? tm : null);
if (transactional) {
tm.begin();
}
boolean lockable = testee.acquirePutFromLoadLock(KEY1);
try {
assertTrue(lockable);
}
finally {
if (lockable) {
testee.releasePutFromLoadLock(KEY1);
}
}
}
public void testRegisteredPut() throws Exception {
registeredPutTest(false);
}
public void testRegisteredPutTransactional() throws Exception {
registeredPutTest(true);
}
private void registeredPutTest(boolean transactional) throws Exception {
PutFromLoadValidator testee = new PutFromLoadValidator(
transactional ? tm : null);
if (transactional) {
tm.begin();
}
testee.registerPendingPut(KEY1);
boolean lockable = testee.acquirePutFromLoadLock(KEY1);
try {
assertTrue(lockable);
}
finally {
if (lockable) {
testee.releasePutFromLoadLock(KEY1);
}
}
}
public void testNakedPutAfterKeyRemoval() throws Exception {
nakedPutAfterRemovalTest(false, false);
}
public void testNakedPutAfterKeyRemovalTransactional() throws Exception {
nakedPutAfterRemovalTest(true, false);
}
public void testNakedPutAfterRegionRemoval() throws Exception {
nakedPutAfterRemovalTest(false, true);
}
public void testNakedPutAfterRegionRemovalTransactional() throws Exception {
nakedPutAfterRemovalTest(true, true);
}
private void nakedPutAfterRemovalTest(boolean transactional,
boolean removeRegion) throws Exception {
PutFromLoadValidator testee = new PutFromLoadValidator(
transactional ? tm : null);
if (removeRegion) {
testee.invalidateRegion();
} else {
testee.invalidateKey(KEY1);
}
if (transactional) {
tm.begin();
}
boolean lockable = testee.acquirePutFromLoadLock(KEY1);
try {
assertFalse(lockable);
}
finally {
if (lockable) {
testee.releasePutFromLoadLock(KEY1);
}
}
}
public void testRegisteredPutAfterKeyRemoval() throws Exception {
registeredPutAfterRemovalTest(false, false);
}
public void testRegisteredPutAfterKeyRemovalTransactional()
throws Exception {
registeredPutAfterRemovalTest(true, false);
}
public void testRegisteredPutAfterRegionRemoval() throws Exception {
registeredPutAfterRemovalTest(false, true);
}
public void testRegisteredPutAfterRegionRemovalTransactional()
throws Exception {
registeredPutAfterRemovalTest(true, true);
}
private void registeredPutAfterRemovalTest(boolean transactional,
boolean removeRegion) throws Exception {
PutFromLoadValidator testee = new PutFromLoadValidator(
transactional ? tm : null);
if (removeRegion) {
testee.invalidateRegion();
} else {
testee.invalidateKey(KEY1);
}
if (transactional) {
tm.begin();
}
testee.registerPendingPut(KEY1);
boolean lockable = testee.acquirePutFromLoadLock(KEY1);
try {
assertTrue(lockable);
}
finally {
if (lockable) {
testee.releasePutFromLoadLock(KEY1);
}
}
}
public void testRegisteredPutWithInterveningKeyRemoval() throws Exception {
registeredPutWithInterveningRemovalTest(false, false);
}
public void testRegisteredPutWithInterveningKeyRemovalTransactional()
throws Exception {
registeredPutWithInterveningRemovalTest(true, false);
}
public void testRegisteredPutWithInterveningRegionRemoval()
throws Exception {
registeredPutWithInterveningRemovalTest(false, true);
}
public void testRegisteredPutWithInterveningRegionRemovalTransactional()
throws Exception {
registeredPutWithInterveningRemovalTest(true, true);
}
private void registeredPutWithInterveningRemovalTest(boolean transactional,
boolean removeRegion) throws Exception {
PutFromLoadValidator testee = new PutFromLoadValidator(
transactional ? tm : null);
if (transactional) {
tm.begin();
}
testee.registerPendingPut(KEY1);
if (removeRegion) {
testee.invalidateRegion();
} else {
testee.invalidateKey(KEY1);
}
boolean lockable = testee.acquirePutFromLoadLock(KEY1);
try {
assertFalse(lockable);
}
finally {
if (lockable) {
testee.releasePutFromLoadLock(KEY1);
}
}
}
public void testDelayedNakedPutAfterKeyRemoval() throws Exception {
delayedNakedPutAfterRemovalTest(false, false);
}
public void testDelayedNakedPutAfterKeyRemovalTransactional()
throws Exception {
delayedNakedPutAfterRemovalTest(true, false);
}
public void testDelayedNakedPutAfterRegionRemoval() throws Exception {
delayedNakedPutAfterRemovalTest(false, true);
}
public void testDelayedNakedPutAfterRegionRemovalTransactional()
throws Exception {
delayedNakedPutAfterRemovalTest(true, true);
}
private void delayedNakedPutAfterRemovalTest(boolean transactional,
boolean removeRegion) throws Exception {
PutFromLoadValidator testee = new TestValidator(transactional ? tm
: null, 100, 1000, 500, 10000);
if (removeRegion) {
testee.invalidateRegion();
} else {
testee.invalidateKey(KEY1);
}
if (transactional) {
tm.begin();
}
Thread.sleep(110);
boolean lockable = testee.acquirePutFromLoadLock(KEY1);
try {
assertTrue(lockable);
}
finally {
if (lockable) {
testee.releasePutFromLoadLock(KEY1);
}
}
}
public void testMultipleRegistrations() throws Exception {
multipleRegistrationtest(false);
}
public void testMultipleRegistrationsTransactional() throws Exception {
multipleRegistrationtest(true);
}
private void multipleRegistrationtest(final boolean transactional) throws Exception {
final PutFromLoadValidator testee = new PutFromLoadValidator(transactional ? tm : null);
final CountDownLatch registeredLatch = new CountDownLatch(3);
final CountDownLatch finishedLatch = new CountDownLatch(3);
final AtomicInteger success = new AtomicInteger();
Runnable r = new Runnable() {
public void run() {
try {
if (transactional) {
tm.begin();
}
testee.registerPendingPut(KEY1);
registeredLatch.countDown();
registeredLatch.await(5, TimeUnit.SECONDS);
if (testee.acquirePutFromLoadLock(KEY1)) {
try {
success.incrementAndGet();
}
finally {
testee.releasePutFromLoadLock(KEY1);
}
}
finishedLatch.countDown();
}
catch (Exception e) {
e.printStackTrace();
}
}
};
ExecutorService executor = Executors.newFixedThreadPool(3);
// Start with a removal so the "isPutValid" calls will fail if
// any of the concurrent activity isn't handled properly
testee.invalidateRegion();
// Do the registration + isPutValid calls
executor.execute(r);
executor.execute(r);
executor.execute(r);
finishedLatch.await(5, TimeUnit.SECONDS);
assertEquals("All threads succeeded", 3, success.get());
}
/**
* White box test for ensuring key removals get cleaned up.
*
* @throws Exception
*/
public void testRemovalCleanup() throws Exception {
TestValidator testee = new TestValidator(null, 200, 1000, 500, 10000);
testee.invalidateKey("KEY1");
testee.invalidateKey("KEY2");
Thread.sleep(210);
assertEquals(2, testee.getRemovalQueueLength());
testee.invalidateKey("KEY1");
assertEquals(2, testee.getRemovalQueueLength());
testee.invalidateKey("KEY2");
assertEquals(2, testee.getRemovalQueueLength());
}
/**
* Very much a white box test of the logic for ensuring pending
* put registrations get cleaned up.
*
* @throws Exception
*/
public void testPendingPutCleanup() throws Exception {
TestValidator testee = new TestValidator(tm, 5000, 600, 300, 900);
// Start with a regionRemoval so we can confirm at the end that all
// registrations have been cleaned out
testee.invalidateRegion();
testee.registerPendingPut("1");
testee.registerPendingPut("2");
testee.registerPendingPut("3");
testee.registerPendingPut("4");
testee.registerPendingPut("5");
testee.registerPendingPut("6");
testee.acquirePutFromLoadLock("6");
testee.releasePutFromLoadLock("6");
testee.acquirePutFromLoadLock("2");
testee.releasePutFromLoadLock("2");
// ppq = [1,2(c),3,4,5,6(c)]
assertEquals(6, testee.getPendingPutQueueLength());
assertEquals(0, testee.getOveragePendingPutQueueLength());
// Sleep past "pendingPutRecentPeriod"
Thread.sleep(310);
testee.registerPendingPut("7");
// White box -- should have cleaned out 2 (completed) but
// not gotten to 6 (also removed)
// ppq = [1,3,4,5,6(c),7]
assertEquals(0, testee.getOveragePendingPutQueueLength());
assertEquals(6, testee.getPendingPutQueueLength());
// Sleep past "pendingPutOveragePeriod"
Thread.sleep(310);
testee.registerPendingPut("8");
// White box -- should have cleaned out 6 (completed) and
// moved 1, 3, 4 and 5 to overage queue
// oppq = [1,3,4,5] ppq = [7,8]
assertEquals(4, testee.getOveragePendingPutQueueLength());
assertEquals(2, testee.getPendingPutQueueLength());
// Sleep past "maxPendingPutDelay"
Thread.sleep(310);
testee.acquirePutFromLoadLock("3");
testee.releasePutFromLoadLock("3");
// White box -- should have cleaned out 1 (overage) and
// moved 7 to overage queue
// oppq = [3(c),4,5,7] ppq=[8]
assertEquals(4, testee.getOveragePendingPutQueueLength());
assertEquals(1, testee.getPendingPutQueueLength());
// Sleep past "maxPendingPutDelay"
Thread.sleep(310);
tm.begin();
testee.registerPendingPut("7");
Transaction tx = tm.suspend();
// White box -- should have cleaned out 3 (completed)
// and 4 (overage) and moved 8 to overage queue
// We now have 5,7,8 in overage and 7tx in pending
// oppq = [5,7,8] ppq=[7tx]
assertEquals(3, testee.getOveragePendingPutQueueLength());
assertEquals(1, testee.getPendingPutQueueLength());
// Validate that only expected items can do puts, thus indirectly
// proving the others have been cleaned out of pendingPuts map
boolean locked = testee.acquirePutFromLoadLock("1");
if (locked) {
testee.releasePutFromLoadLock("1");
}
assertFalse(locked);
// 5 was overage, so should have been cleaned
assertEquals(2, testee.getOveragePendingPutQueueLength());
locked = testee.acquirePutFromLoadLock("2");
if (locked) {
testee.releasePutFromLoadLock("1");
}
assertFalse(locked);
// 7 was overage, so should have been cleaned
assertEquals(1, testee.getOveragePendingPutQueueLength());
locked = testee.acquirePutFromLoadLock("3");
if (locked) {
testee.releasePutFromLoadLock("1");
}
assertFalse(locked);
locked = testee.acquirePutFromLoadLock("4");
if (locked) {
testee.releasePutFromLoadLock("1");
}
assertFalse(locked);
locked = testee.acquirePutFromLoadLock("5");
if (locked) {
testee.releasePutFromLoadLock("1");
}
assertFalse(locked);
locked = testee.acquirePutFromLoadLock("1");
if (locked) {
testee.releasePutFromLoadLock("1");
}
assertFalse(testee.acquirePutFromLoadLock("6"));
locked = testee.acquirePutFromLoadLock("7");
if (locked) {
testee.releasePutFromLoadLock("1");
}
assertFalse(locked);
assertTrue(testee.acquirePutFromLoadLock("8"));
testee.releasePutFromLoadLock("8");
tm.resume(tx);
assertTrue(testee.acquirePutFromLoadLock("7"));
testee.releasePutFromLoadLock("7");
}
public void testInvalidateKeyBlocksForInProgressPut() throws Exception {
invalidationBlocksForInProgressPutTest(true);
}
public void testInvalidateRegionBlocksForInProgressPut() throws Exception {
invalidationBlocksForInProgressPutTest(false);
}
private void invalidationBlocksForInProgressPutTest(final boolean keyOnly) throws Exception {
final PutFromLoadValidator testee = new PutFromLoadValidator(null);
final CountDownLatch removeLatch = new CountDownLatch(1);
final CountDownLatch pferLatch = new CountDownLatch(1);
final AtomicReference<Object> cache = new AtomicReference<Object>("INITIAL");
Callable<Boolean> pferCallable = new Callable<Boolean>() {
public Boolean call() throws Exception {
testee.registerPendingPut(KEY1);
if (testee.acquirePutFromLoadLock(KEY1)) {
try {
removeLatch.countDown();
pferLatch.await();
cache.set("PFER");
return Boolean.TRUE;
}
finally {
testee.releasePutFromLoadLock(KEY1);
}
}
return Boolean.FALSE;
}
};
Callable<Void> invalidateCallable = new Callable<Void>() {
public Void call() throws Exception {
removeLatch.await();
if (keyOnly) {
testee.invalidateKey(KEY1);
}
else {
testee.invalidateRegion();
}
cache.set(null);
return null;
}
};
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Boolean> pferFuture = executorService.submit(pferCallable);
Future<Void> invalidateFuture = executorService.submit(invalidateCallable);
try {
invalidateFuture.get(1, TimeUnit.SECONDS);
fail("invalidateFuture did not block");
}
catch (TimeoutException good) {}
pferLatch.countDown();
assertTrue(pferFuture.get(5, TimeUnit.SECONDS));
invalidateFuture.get(5, TimeUnit.SECONDS);
assertNull(cache.get());
}
private static class TestValidator extends PutFromLoadValidator {
protected TestValidator(TransactionManager transactionManager,
long nakedPutInvalidationPeriod, long pendingPutOveragePeriod,
long pendingPutRecentPeriod, long maxPendingPutDelay) {
super(transactionManager, nakedPutInvalidationPeriod,
pendingPutOveragePeriod, pendingPutRecentPeriod,
maxPendingPutDelay);
}
@Override
public int getOveragePendingPutQueueLength() {
return super.getOveragePendingPutQueueLength();
}
@Override
public int getPendingPutQueueLength() {
return super.getPendingPutQueueLength();
}
@Override
public int getRemovalQueueLength() {
return super.getRemovalQueueLength();
}
}
}

View File

@ -1,76 +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.test.cache.jbc.builder;
import org.hibernate.cache.jbc.CacheInstanceManager;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.cache.jbc.AbstractJBossCacheTestCase;
import org.hibernate.test.util.CacheTestUtil;
/**
* A CacheInstanceManagerTestBase.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class CacheInstanceManagerTestBase extends AbstractJBossCacheTestCase {
/**
* Create a new CacheInstanceManagerTestBase.
*
* @param name The test name
*/
public CacheInstanceManagerTestBase(String name) {
super(name);
}
protected abstract Class getRegionFactoryClass();
public void testUse2ndLevelCache() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("", getRegionFactoryClass(), false, true);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
CacheInstanceManager cim = regionFactory.getCacheInstanceManager();
assertNull(cim.getCollectionCacheInstance());
assertNull(cim.getEntityCacheInstance());
assertNotNull(cim.getQueryCacheInstance());
assertNotNull(cim.getTimestampsCacheInstance());
}
public void testUseQueryCache() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("", getRegionFactoryClass(), true, false);
JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
CacheInstanceManager cim = regionFactory.getCacheInstanceManager();
assertNotNull(cim.getCollectionCacheInstance());
assertNotNull(cim.getEntityCacheInstance());
assertNull(cim.getQueryCacheInstance());
assertNull(cim.getTimestampsCacheInstance());
}
}

View File

@ -1,51 +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.test.cache.jbc.builder;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
/**
* A SharedCacheInstanceManagerTestCase.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MultiplexedCacheInstanceManagerTestCase extends CacheInstanceManagerTestBase {
/**
* Create a new SharedCacheInstanceManagerTestCase.
*
* @param name test name
*/
public MultiplexedCacheInstanceManagerTestCase(String name) {
super(name);
}
@Override
protected Class getRegionFactoryClass() {
return MultiplexedJBossCacheRegionFactory.class;
}
}

View File

@ -1,50 +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.test.cache.jbc.builder;
import org.hibernate.cache.jbc.SharedJBossCacheRegionFactory;
/**
* A SharedCacheInstanceManagerTestCase.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class SharedCacheInstanceManagerTestCase extends CacheInstanceManagerTestBase {
/**
* Create a new SharedCacheInstanceManagerTestCase.
*
* @param name test name
*/
public SharedCacheInstanceManagerTestCase(String name) {
super(name);
}
@Override
protected Class getRegionFactoryClass() {
return SharedJBossCacheRegionFactory.class;
}
}

View File

@ -1,587 +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.test.cache.jbc.collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.extensions.TestSetup;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.impl.CacheDataDescriptionImpl;
import org.hibernate.cache.jbc.BasicRegionAdapter;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc.collection.CollectionRegionImpl;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cache.jbc.util.NonLockingDataVersion;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.cache.jbc.AbstractJBossCacheTestCase;
import org.hibernate.test.util.CacheTestUtil;
import org.hibernate.util.ComparableComparator;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.transaction.BatchModeTransactionManager;
/**
* Base class for tests of CollectionRegionAccessStrategy impls.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractCollectionRegionAccessStrategyTestCase extends AbstractJBossCacheTestCase {
public static final String REGION_NAME = "test/com.foo.test";
public static final String KEY_BASE = "KEY";
public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2";
protected static int testCount;
protected static Configuration localCfg;
protected static JBossCacheRegionFactory localRegionFactory;
protected static Cache localCache;
protected static Configuration remoteCfg;
protected static JBossCacheRegionFactory remoteRegionFactory;
protected static Cache remoteCache;
protected CollectionRegion localCollectionRegion;
protected CollectionRegionAccessStrategy localAccessStrategy;
protected CollectionRegion remoteCollectionRegion;
protected CollectionRegionAccessStrategy remoteAccessStrategy;
protected boolean invalidation;
protected boolean optimistic;
protected boolean synchronous;
protected Exception node1Exception;
protected Exception node2Exception;
protected AssertionFailedError node1Failure;
protected AssertionFailedError node2Failure;
public static Test getTestSetup(Class testClass, String configName) {
TestSuite suite = new TestSuite(testClass);
return new AccessStrategyTestSetup(suite, configName);
}
public static Test getTestSetup(Test test, String configName) {
return new AccessStrategyTestSetup(test, configName);
}
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public AbstractCollectionRegionAccessStrategyTestCase(String name) {
super(name);
}
protected abstract AccessType getAccessType();
protected void setUp() throws Exception {
super.setUp();
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
invalidation = CacheHelper.isClusteredInvalidation(localCache);
synchronous = CacheHelper.isSynchronous(localCache);
optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
localCollectionRegion = localRegionFactory.buildCollectionRegion(REGION_NAME, localCfg.getProperties(), getCacheDataDescription());
localAccessStrategy = localCollectionRegion.buildAccessStrategy(getAccessType());
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
remoteCollectionRegion = remoteRegionFactory.buildCollectionRegion(REGION_NAME, remoteCfg.getProperties(), getCacheDataDescription());
remoteAccessStrategy = remoteCollectionRegion.buildAccessStrategy(getAccessType());
node1Exception = null;
node2Exception = null;
node1Failure = null;
node2Failure = null;
}
protected void tearDown() throws Exception {
super.tearDown();
if (localCollectionRegion != null)
localCollectionRegion.destroy();
if (remoteCollectionRegion != null)
remoteCollectionRegion.destroy();
try {
localCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
localCache.removeNode(Fqn.ROOT);
}
catch (Exception e) {
log.error("Problem purging local cache" ,e);
}
try {
remoteCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
remoteCache.removeNode(Fqn.ROOT);
}
catch (Exception e) {
log.error("Problem purging remote cache" ,e);
}
node1Exception = null;
node2Exception = null;
node1Failure = null;
node2Failure = null;
}
protected static Configuration createConfiguration(String configName, String configResource) {
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, configName);
if (configResource != null) {
cfg.setProperty(MultiplexingCacheInstanceManager.CACHE_FACTORY_RESOURCE_PROP, configResource);
}
return cfg;
}
protected CacheDataDescription getCacheDataDescription() {
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
}
protected boolean isUsingOptimisticLocking() {
return optimistic;
}
public boolean isBlockingReads()
{
return !isUsingOptimisticLocking();
}
protected boolean isUsingInvalidation() {
return invalidation;
}
protected boolean isSynchronous() {
return synchronous;
}
protected Fqn getRegionFqn(String regionName, String regionPrefix) {
return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, CollectionRegionImpl.TYPE);
}
/**
* This is just a setup test where we assert that the cache config is
* as we expected.
*/
public abstract void testCacheConfiguration();
/**
* Test method for {@link TransactionalAccess#getRegion()}.
*/
public void testGetRegion() {
assertEquals("Correct region", localCollectionRegion, localAccessStrategy.getRegion());
}
/**
* Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}.
*/
public void testPutFromLoad() throws Exception {
putFromLoadTest(false);
}
/**
* Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}.
*/
public void testPutFromLoadMinimal() throws Exception {
putFromLoadTest(true);
}
/**
* Simulate 2 nodes, both start, tx do a get, experience a cache miss,
* then 'read from db.' First does a putFromLoad, then an evict (to represent a change).
* Second tries to do a putFromLoad with stale data (i.e. it took
* longer to read from the db). Both commit their tx. Then
* both start a new tx and get. First should see the updated data;
* second should either see the updated data (isInvalidation()( == false)
* or null (isInvalidation() == true).
*
* @param useMinimalAPI
* @throws Exception
*/
private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
final String KEY = KEY_BASE + testCount++;
final CountDownLatch writeLatch1 = new CountDownLatch(1);
final CountDownLatch writeLatch2 = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(2);
Thread node1 = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertEquals("node1 starts clean", null, localAccessStrategy.get(KEY, txTimestamp));
writeLatch1.await();
if (useMinimalAPI) {
localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2), true);
}
else {
localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2));
}
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
// Let node2 write
writeLatch2.countDown();
completionLatch.countDown();
}
}
};
Thread node2 = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertNull("node2 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
// Let node1 write
writeLatch1.countDown();
// Wait for node1 to finish
writeLatch2.await();
// Let the first PFER propagate
sleep(200);
if (useMinimalAPI) {
remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
}
else {
remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
}
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node2 caught exception", e);
node2Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node2Failure = e;
rollback();
}
finally {
completionLatch.countDown();
}
}
};
node1.setDaemon(true);
node2.setDaemon(true);
node1.start();
node2.start();
assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
if (node1Failure != null)
throw node1Failure;
if (node2Failure != null)
throw node2Failure;
assertEquals("node1 saw no exceptions", null, node1Exception);
assertEquals("node2 saw no exceptions", null, node2Exception);
// let the final PFER propagate
sleep(100);
long txTimestamp = System.currentTimeMillis();
String msg1 = "Correct node1 value";
String msg2 = "Correct node2 value";
Object expected1 = null;
Object expected2 = null;
if (isUsingInvalidation()) {
// PFER does not generate any invalidation, so each node should
// succeed. We count on database locking and Hibernate removing
// the collection on any update to prevent the situation we have
// here where the caches have inconsistent data
expected1 = VALUE2;
expected2 = VALUE1;
}
else {
// the initial VALUE2 should prevent the node2 put
expected1 = VALUE2;
expected2 = VALUE2;
}
assertEquals(msg1, expected1, localAccessStrategy.get(KEY, txTimestamp));
assertEquals(msg2, expected2, remoteAccessStrategy.get(KEY, txTimestamp));
}
/**
* Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
*/
public void testRemove() {
evictOrRemoveTest(false);
}
/**
* Test method for {@link TransactionalAccess#removeAll()}.
*/
public void testRemoveAll() {
evictOrRemoveAllTest(false);
}
/**
* Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the CollectionRegionAccessStrategy API.
*/
public void testEvict() {
evictOrRemoveTest(true);
}
/**
* Test method for {@link TransactionalAccess#evictAll()}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the CollectionRegionAccessStrategy API.
*/
public void testEvictAll() {
evictOrRemoveAllTest(true);
}
private void evictOrRemoveTest(boolean evict) {
final String KEY = KEY_BASE + testCount++;
assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
// Wait for async propagation
sleep(250);
if (evict)
localAccessStrategy.evict(KEY);
else
localAccessStrategy.remove(KEY);
assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
private void evictOrRemoveAllTest(boolean evict) {
final String KEY = KEY_BASE + testCount++;
Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
Node regionRoot = localCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (isUsingOptimisticLocking()) {
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (isUsingOptimisticLocking()) {
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
// Wait for async propagation
sleep(250);
if (isUsingOptimisticLocking()) {
regionRoot = localCache.getRoot().getChild(regionFqn);
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
if (evict)
localAccessStrategy.evictAll();
else
localAccessStrategy.removeAll();
// This should re-establish the region root node
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
regionRoot = localCache.getRoot().getChild(regionFqn);
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);
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()));
// Revalidate the region root
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Region root should have 1 child -- the one we added above
assertEquals(1, getValidChildrenCount(regionRoot));
// Wait for async propagation of the putFromLoad
sleep(250);
assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
private void rollback() {
try {
BatchModeTransactionManager.getInstance().rollback();
}
catch (Exception e) {
log.error(e.getMessage(), e);
}
}
private static class AccessStrategyTestSetup extends TestSetup {
private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
private final String configResource;
private final String configName;
private String preferIPv4Stack;
public AccessStrategyTestSetup(Test test, String configName) {
this(test, configName, null);
}
public AccessStrategyTestSetup(Test test, String configName, String configResource) {
super(test);
this.configName = configName;
this.configResource = configResource;
}
@Override
protected void setUp() throws Exception {
super.setUp();
// Try to ensure we use IPv4; otherwise cluster formation is very slow
preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
System.setProperty(PREFER_IPV4STACK, "true");
localCfg = createConfiguration(configName, configResource);
localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
localCache = localRegionFactory.getCacheInstanceManager().getCollectionCacheInstance();
remoteCfg = createConfiguration(configName, configResource);
remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteCfg);
remoteCache = remoteRegionFactory.getCacheInstanceManager().getCollectionCacheInstance();
}
@Override
protected void tearDown() throws Exception {
try {
super.tearDown();
}
finally {
if (preferIPv4Stack == null)
System.clearProperty(PREFER_IPV4STACK);
else
System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
}
if (localRegionFactory != null)
localRegionFactory.stop();
if (remoteRegionFactory != null)
remoteRegionFactory.stop();
}
}
}

View File

@ -1,49 +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.test.cache.jbc.collection;
import org.hibernate.cache.access.AccessType;
/**
* Base class for tests of TRANSACTIONAL access.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractReadOnlyAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
/**
* Create a new AbstractTransactionalAccessTestCase.
*
*/
public AbstractReadOnlyAccessTestCase(String name) {
super(name);
}
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
}

View File

@ -1,49 +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.test.cache.jbc.collection;
import org.hibernate.cache.access.AccessType;
/**
* Base class for tests of TRANSACTIONAL access.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractTransactionalAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
/**
* Create a new AbstractTransactionalAccessTestCase.
*
*/
public AbstractTransactionalAccessTestCase(String name) {
super(name);
}
@Override
protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
}
}

View File

@ -1,118 +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.test.cache.jbc.collection;
import java.util.Properties;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.Region;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.jbc.BasicRegionAdapter;
import org.hibernate.cache.jbc.CacheInstanceManager;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.collection.CollectionRegionImpl;
import org.hibernate.test.cache.jbc.AbstractEntityCollectionRegionTestCase;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
/**
* Tests of CollectionRegionImpl.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
/**
* Create a new EntityRegionImplTestCase.
*
* @param name
*/
public CollectionRegionImplTestCase(String name) {
super(name);
}
@Override
protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
CollectionRegion region = regionFactory.buildCollectionRegion("test", properties, null);
assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
try
{
region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
fail("Did not get READ_ONLY");
}
catch (UnsupportedOperationException good) {}
try
{
region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
fail("Incorrectly got NONSTRICT_READ_WRITE");
}
catch (CacheException good) {}
try
{
region.buildAccessStrategy(AccessType.READ_WRITE);
fail("Incorrectly got READ_WRITE");
}
catch (CacheException good) {}
}
@Override
protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
return regionFactory.buildCollectionRegion(regionName, properties, cdd);
}
@Override
protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
return mgr.getCollectionCacheInstance();
}
@Override
protected Fqn getRegionFqn(String regionName, String regionPrefix) {
return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, CollectionRegionImpl.TYPE);
}
@Override
protected void putInRegion(Region region, Object key, Object value) {
CollectionRegionAccessStrategy strategy = ((CollectionRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL);
// // putFromLoad is ignored if not preceded by a get, so do a get
// strategy.get(key, System.currentTimeMillis());
strategy.putFromLoad(key, value, System.currentTimeMillis(), new Integer(1));
}
@Override
protected void removeFromRegion(Region region, Object key) {
((CollectionRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).remove(key);
}
}

View File

@ -1,62 +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.test.cache.jbc.collection;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests TRANSACTIONAL access when pessimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public MvccInvalidatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(MvccInvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "mvcc-entity");
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
// Known failures
}

View File

@ -1,72 +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.test.cache.jbc.collection;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this
* version using pessimistic locking with READ_ONLY access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
private static CollectionRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public MvccReadOnlyExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "mvcc-entity";
}
@Override
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,63 +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.test.cache.jbc.collection;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests READ_ONLY access when pessimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public MvccReadOnlyTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(MvccReadOnlyTestCase.class);
return getTestSetup(suite, "mvcc-entity");
}
// Known failures
// Overrides
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,58 +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.test.cache.jbc.collection;
import junit.framework.Test;
/**
* Tests TRANSACTIONAL access when pessimistic locking and replication are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public MvccReplicatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
return getTestSetup(MvccReplicatedTransactionalTestCase.class, "mvcc-shared");
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,72 +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.test.cache.jbc.collection;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this base
* version using Optimistic locking with TRANSACTIONAL access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
private static CollectionRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public MvccTransactionalExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "mvcc-entity";
}
@Override
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,61 +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.test.cache.jbc.collection;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests TRANSACTIONAL access when optimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticInvalidatedTransactionalTestCase
extends AbstractTransactionalAccessTestCase {
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public OptimisticInvalidatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(OptimisticInvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "optimistic-entity");
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,93 +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.test.cache.jbc.collection;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this
* version using Optimistic locking with READ_ONLY access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticReadOnlyExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
private static CollectionRegionAccessStrategy localAccessStrategy;
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public OptimisticReadOnlyExtraAPITestCase(String name) {
super(name);
}
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
@Override
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
/**
* Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
*/
@Override
public void testLockItem() {
try {
getCollectionAccessStrategy().lockItem(KEY, new Integer(1));
fail("Call to lockItem did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
/**
* Test method for {@link TransactionalAccess#lockRegion()}.
*/
@Override
public void testLockRegion() {
try {
getCollectionAccessStrategy().lockRegion();
fail("Call to lockRegion did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
}

View File

@ -1,60 +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.test.cache.jbc.collection;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests READ_ONLY access when optimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public OptimisticReadOnlyTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(OptimisticReadOnlyTestCase.class);
return getTestSetup(suite, "optimistic-entity");
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,58 +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.test.cache.jbc.collection;
import junit.framework.Test;
/**
* Tests TRANSACTIONAL access when optimistic locking and replication are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public OptimisticReplicatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
return getTestSetup(OptimisticReplicatedTransactionalTestCase.class, "optimistic-shared");
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Invalidation", isUsingInvalidation());
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,158 +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.test.cache.jbc.collection;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.cache.jbc.AbstractJBossCacheTestCase;
import org.hibernate.test.util.CacheTestUtil;
import org.jboss.cache.Cache;
/**
* Tests for the "extra API" in CollectionRegionAccessStrategy; in this base
* version using Optimistic locking with TRANSACTIONAL access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticTransactionalExtraAPITestCase extends AbstractJBossCacheTestCase {
public static final String REGION_NAME = "test/com.foo.test";
public static final String KEY = "KEY";
public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2";
private static CollectionRegionAccessStrategy localAccessStrategy;
private static boolean optimistic;
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public OptimisticTransactionalExtraAPITestCase(String name) {
super(name);
}
protected void setUp() throws Exception {
super.setUp();
if (getCollectionAccessStrategy() == null) {
Configuration cfg = createConfiguration();
JBossCacheRegionFactory rf = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
Cache localCache = rf.getCacheInstanceManager().getEntityCacheInstance();
optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
CollectionRegion localCollectionRegion = rf.buildCollectionRegion(REGION_NAME, cfg.getProperties(), null);
setCollectionAccessStrategy(localCollectionRegion.buildAccessStrategy(getAccessType()));
}
}
protected void tearDown() throws Exception {
super.tearDown();
}
protected Configuration createConfiguration() {
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
return cfg;
}
protected String getCacheConfigName() {
return "optimistic-entity";
}
protected boolean isUsingOptimisticLocking() {
return optimistic;
}
protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
}
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return localAccessStrategy;
}
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
/**
* This is just a setup test where we assert that the cache config is
* as we expected.
*/
public void testCacheConfiguration() {
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
}
/**
* Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
*/
public void testLockItem() {
assertNull(getCollectionAccessStrategy().lockItem(KEY, new Integer(1)));
}
/**
* Test method for {@link TransactionalAccess#lockRegion()}.
*/
public void testLockRegion() {
assertNull(getCollectionAccessStrategy().lockRegion());
}
/**
* Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
*/
public void testUnlockItem() {
getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
/**
* Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
*/
public void testUnlockRegion() {
getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
public static class MockSoftLock implements SoftLock {
}
}

View File

@ -1,62 +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.test.cache.jbc.collection;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests TRANSACTIONAL access when pessimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public PessimisticInvalidatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(PessimisticInvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "pessimistic-entity");
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
// Known failures
}

View File

@ -1,72 +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.test.cache.jbc.collection;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this
* version using pessimistic locking with READ_ONLY access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
private static CollectionRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public PessimisticReadOnlyExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "pessimistic-entity";
}
@Override
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,63 +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.test.cache.jbc.collection;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests READ_ONLY access when pessimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public PessimisticReadOnlyTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(PessimisticReadOnlyTestCase.class);
return getTestSetup(suite, "pessimistic-entity");
}
// Known failures
// Overrides
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,58 +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.test.cache.jbc.collection;
import junit.framework.Test;
/**
* Tests TRANSACTIONAL access when pessimistic locking and replication are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public PessimisticReplicatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
return getTestSetup(PessimisticReplicatedTransactionalTestCase.class, "pessimistic-shared");
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,72 +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.test.cache.jbc.collection;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this base
* version using Optimistic locking with TRANSACTIONAL access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
private static CollectionRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public PessimisticTransactionalExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "pessimistic-entity";
}
@Override
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,809 +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.test.cache.jbc.entity;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.extensions.TestSetup;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.impl.CacheDataDescriptionImpl;
import org.hibernate.cache.jbc.BasicRegionAdapter;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc.entity.EntityRegionImpl;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
import org.hibernate.cache.jbc.util.CacheHelper;
import org.hibernate.cache.jbc.util.NonLockingDataVersion;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.cache.jbc.AbstractJBossCacheTestCase;
import org.hibernate.test.util.CacheTestUtil;
import org.hibernate.util.ComparableComparator;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.transaction.BatchModeTransactionManager;
/**
* Base class for tests of EntityRegionAccessStrategy impls.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractEntityRegionAccessStrategyTestCase extends AbstractJBossCacheTestCase {
public static final String REGION_NAME = "test/com.foo.test";
public static final String KEY_BASE = "KEY";
public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2";
protected static int testCount;
protected static Configuration localCfg;
protected static JBossCacheRegionFactory localRegionFactory;
protected static Cache localCache;
protected static Configuration remoteCfg;
protected static JBossCacheRegionFactory remoteRegionFactory;
protected static Cache remoteCache;
protected static boolean invalidation;
protected static boolean optimistic;
protected static boolean synchronous;
protected EntityRegion localEntityRegion;
protected EntityRegionAccessStrategy localAccessStrategy;
protected EntityRegion remoteEntityRegion;
protected EntityRegionAccessStrategy remoteAccessStrategy;
protected Exception node1Exception;
protected Exception node2Exception;
protected AssertionFailedError node1Failure;
protected AssertionFailedError node2Failure;
public static Test getTestSetup(Class testClass, String configName) {
return getTestSetup(testClass, configName, null);
}
public static Test getTestSetup(Test test, String configName) {
return getTestSetup(test, configName, null);
}
public static Test getTestSetup(Class testClass, String configName, String configResource) {
TestSuite suite = new TestSuite(testClass);
return new AccessStrategyTestSetup(suite, configName, configResource);
}
public static Test getTestSetup(Test test, String configName, String configResource) {
return new AccessStrategyTestSetup(test, configName, configResource);
}
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public AbstractEntityRegionAccessStrategyTestCase(String name) {
super(name);
}
protected abstract AccessType getAccessType();
protected void setUp() throws Exception {
super.setUp();
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
localEntityRegion = localRegionFactory.buildEntityRegion(REGION_NAME, localCfg.getProperties(), getCacheDataDescription());
localAccessStrategy = localEntityRegion.buildAccessStrategy(getAccessType());
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
remoteEntityRegion = remoteRegionFactory.buildEntityRegion(REGION_NAME, remoteCfg.getProperties(), getCacheDataDescription());
remoteAccessStrategy = remoteEntityRegion.buildAccessStrategy(getAccessType());
node1Exception = null;
node2Exception = null;
node1Failure = null;
node2Failure = null;
}
protected void tearDown() throws Exception {
super.tearDown();
if (localEntityRegion != null)
localEntityRegion.destroy();
if (remoteEntityRegion != null)
remoteEntityRegion.destroy();
try {
localCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
localCache.removeNode(Fqn.ROOT);
}
catch (Exception e) {
log.error("Problem purging local cache" ,e);
}
try {
remoteCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
remoteCache.removeNode(Fqn.ROOT);
}
catch (Exception e) {
log.error("Problem purging remote cache" ,e);
}
node1Exception = null;
node2Exception = null;
node1Failure = null;
node2Failure = null;
}
protected static Configuration createConfiguration(String configName, String configResource) {
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, configName);
if (configResource != null) {
cfg.setProperty(MultiplexingCacheInstanceManager.CACHE_FACTORY_RESOURCE_PROP, configResource);
}
return cfg;
}
protected CacheDataDescription getCacheDataDescription() {
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
}
protected boolean isUsingOptimisticLocking() {
return optimistic;
}
protected boolean isUsingInvalidation() {
return invalidation;
}
protected boolean isSynchronous() {
return synchronous;
}
protected Fqn getRegionFqn(String regionName, String regionPrefix) {
return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, EntityRegionImpl.TYPE);
}
protected void assertThreadsRanCleanly()
{
if (node1Failure != null)
throw node1Failure;
if (node2Failure != null)
throw node2Failure;
if (node1Exception != null) {
log.error("node1 saw an exception", node1Exception);
assertEquals("node1 saw no exceptions", null, node1Exception);
}
if (node2Exception != null) {
log.error("node2 saw an exception", node2Exception);
assertEquals("node2 saw no exceptions", null, node2Exception);
}
}
/**
* This is just a setup test where we assert that the cache config is
* as we expected.
*/
public abstract void testCacheConfiguration();
/**
* Test method for {@link TransactionalAccess#getRegion()}.
*/
public void testGetRegion() {
assertEquals("Correct region", localEntityRegion, localAccessStrategy.getRegion());
}
/**
* Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}.
*/
public void testPutFromLoad() throws Exception {
putFromLoadTest(false);
}
/**
* Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}.
*/
public void testPutFromLoadMinimal() throws Exception {
putFromLoadTest(true);
}
/**
* Simulate 2 nodes, both start, tx do a get, experience a cache miss,
* then 'read from db.' First does a putFromLoad, then an update.
* Second tries to do a putFromLoad with stale data (i.e. it took
* longer to read from the db). Both commit their tx. Then
* both start a new tx and get. First should see the updated data;
* second should either see the updated data (isInvalidation() == false)
* or null (isInvalidation() == true).
*
* @param useMinimalAPI
* @throws Exception
*/
private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
final String KEY = KEY_BASE + testCount++;
final CountDownLatch writeLatch1 = new CountDownLatch(1);
final CountDownLatch writeLatch2 = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(2);
Thread node1 = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertNull("node1 starts clean", localAccessStrategy.get(KEY, txTimestamp));
writeLatch1.await();
if (useMinimalAPI) {
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
}
else {
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
}
localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
// Let node2 write
writeLatch2.countDown();
completionLatch.countDown();
}
}
};
Thread node2 = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertNull("node1 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
// Let node1 write
writeLatch1.countDown();
// Wait for node1 to finish
writeLatch2.await();
if (useMinimalAPI) {
remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
}
else {
remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
}
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node2 caught exception", e);
node2Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node2Failure = e;
rollback();
}
finally {
completionLatch.countDown();
}
}
};
node1.setDaemon(true);
node2.setDaemon(true);
node1.start();
node2.start();
assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
assertThreadsRanCleanly();
long txTimestamp = System.currentTimeMillis();
assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
if (isUsingInvalidation()) {
if (isUsingOptimisticLocking())
// The node is "deleted" but it's ghost data version prevents the stale node2 PFER
assertEquals("Correct node2 value", null, remoteAccessStrategy.get(KEY, txTimestamp));
else {
// no data version to prevent the PFER; we count on db locks preventing this
assertEquals("Expected node2 value", VALUE1, remoteAccessStrategy.get(KEY, txTimestamp));
}
}
else {
// The node1 update is replicated, preventing the node2 PFER
assertEquals("Correct node2 value", VALUE2, remoteAccessStrategy.get(KEY, txTimestamp));
}
}
/**
* Test method for {@link TransactionalAccess#insert(java.lang.Object, java.lang.Object, java.lang.Object)}.
*/
public void testInsert() throws Exception {
final String KEY = KEY_BASE + testCount++;
final CountDownLatch readLatch = new CountDownLatch(1);
final CountDownLatch commitLatch = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(2);
Thread inserter = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertNull("Correct initial value", localAccessStrategy.get(KEY, txTimestamp));
localAccessStrategy.insert(KEY, VALUE1, new Integer(1));
readLatch.countDown();
commitLatch.await();
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
completionLatch.countDown();
}
}
};
Thread reader = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
readLatch.await();
Object expected = !isBlockingReads() ? null : VALUE1;
assertEquals("Correct initial value", expected, localAccessStrategy.get(KEY, txTimestamp));
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
commitLatch.countDown();
completionLatch.countDown();
}
}
};
inserter.setDaemon(true);
reader.setDaemon(true);
inserter.start();
reader.start();
if (! isBlockingReads())
assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
else {
// Reader should be blocking for lock
assertFalse("Threads completed", completionLatch.await(250, TimeUnit.MILLISECONDS));
commitLatch.countDown();
assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
}
assertThreadsRanCleanly();
long txTimestamp = System.currentTimeMillis();
assertEquals("Correct node1 value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
Object expected = isUsingInvalidation() ? null : VALUE1;
assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
}
public boolean isBlockingReads()
{
return !isUsingOptimisticLocking();
}
/**
* Test method for {@link TransactionalAccess#update(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)}.
*/
public void testUpdate() throws Exception {
final String KEY = KEY_BASE + testCount++;
// Set up initial state
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
// Let the async put propagate
sleep(250);
final CountDownLatch readLatch = new CountDownLatch(1);
final CountDownLatch commitLatch = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(2);
Thread updater = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
readLatch.countDown();
commitLatch.await();
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
completionLatch.countDown();
}
}
};
Thread reader = new Thread() {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
readLatch.await();
// This will block w/ pessimistic locking and then
// read the new value; w/ optimistic it shouldn't
// block and will read the old value
Object expected = !isBlockingReads() ? VALUE1 : VALUE2;
assertEquals("Correct value", expected, localAccessStrategy.get(KEY, txTimestamp));
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
commitLatch.countDown();
completionLatch.countDown();
}
}
};
updater.setDaemon(true);
reader.setDaemon(true);
updater.start();
reader.start();
if (! isBlockingReads())
// Should complete promptly
assertTrue(completionLatch.await(1, TimeUnit.SECONDS));
else {
// Reader thread should be blocking
assertFalse(completionLatch.await(250, TimeUnit.MILLISECONDS));
// Let the writer commit down
commitLatch.countDown();
assertTrue(completionLatch.await(1, TimeUnit.SECONDS));
}
assertThreadsRanCleanly();
long txTimestamp = System.currentTimeMillis();
assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
Object expected = isUsingInvalidation() ? null : VALUE2;
assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
}
/**
* Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
*/
public void testRemove() {
evictOrRemoveTest(false);
}
/**
* Test method for {@link TransactionalAccess#removeAll()}.
*/
public void testRemoveAll() {
evictOrRemoveAllTest(false);
}
/**
* Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the EntityRegionAccessStrategy API.
*/
public void testEvict() {
evictOrRemoveTest(true);
}
/**
* Test method for {@link TransactionalAccess#evictAll()}.
*
* FIXME add testing of the "immediately without regard for transaction
* isolation" bit in the EntityRegionAccessStrategy API.
*/
public void testEvictAll() {
evictOrRemoveAllTest(true);
}
private void evictOrRemoveTest(boolean evict) {
final String KEY = KEY_BASE + testCount++;
assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
// Wait for async propagation
sleep(250);
if (evict)
localAccessStrategy.evict(KEY);
else
localAccessStrategy.remove(KEY);
assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
// sleep(1000);
assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
private void evictOrRemoveAllTest(boolean evict) {
final String KEY = KEY_BASE + testCount++;
Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
Node regionRoot = localCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (isUsingOptimisticLocking()) {
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertEquals(0, getValidChildrenCount(regionRoot));
assertTrue(regionRoot.isResident());
if (isUsingOptimisticLocking()) {
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
// Wait for async propagation
sleep(250);
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
// Wait for async propagation
sleep(250);
if (isUsingOptimisticLocking()) {
regionRoot = localCache.getRoot().getChild(regionFqn);
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
}
if (evict)
localAccessStrategy.evictAll();
else
localAccessStrategy.removeAll();
// This should re-establish the region root node in the optimistic case
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
regionRoot = localCache.getRoot().getChild(regionFqn);
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);
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()));
// Revalidate the region root
regionRoot = remoteCache.getRoot().getChild(regionFqn);
assertFalse(regionRoot == null);
assertTrue(regionRoot.isValid());
assertTrue(regionRoot.isResident());
// Region root should have 1 child -- the one we added above
assertEquals(1, getValidChildrenCount(regionRoot));
// Wait for async propagation
sleep(250);
assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
protected void rollback() {
try {
BatchModeTransactionManager.getInstance().rollback();
}
catch (Exception e) {
log.error(e.getMessage(), e);
}
}
private static class AccessStrategyTestSetup extends TestSetup {
private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
private final String configResource;
private final String configName;
private String preferIPv4Stack;
public AccessStrategyTestSetup(Test test, String configName) {
this(test, configName, null);
}
public AccessStrategyTestSetup(Test test, String configName, String configResource) {
super(test);
this.configName = configName;
this.configResource = configResource;
}
@Override
protected void setUp() throws Exception {
try {
super.tearDown();
}
finally {
if (preferIPv4Stack == null)
System.clearProperty(PREFER_IPV4STACK);
else
System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
}
// Try to ensure we use IPv4; otherwise cluster formation is very slow
preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
System.setProperty(PREFER_IPV4STACK, "true");
localCfg = createConfiguration(configName, configResource);
localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
localCache = localRegionFactory.getCacheInstanceManager().getEntityCacheInstance();
remoteCfg = createConfiguration(configName, configResource);
remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteCfg);
remoteCache = remoteRegionFactory.getCacheInstanceManager().getEntityCacheInstance();
invalidation = CacheHelper.isClusteredInvalidation(localCache);
synchronous = CacheHelper.isSynchronous(localCache);
optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
if (localRegionFactory != null)
localRegionFactory.stop();
if (remoteRegionFactory != null)
remoteRegionFactory.stop();
}
}
}

View File

@ -1,93 +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.test.cache.jbc.entity;
import org.hibernate.cache.access.AccessType;
import org.jboss.cache.transaction.BatchModeTransactionManager;
/**
* Base class for tests of TRANSACTIONAL access.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
/**
* Create a new AbstractTransactionalAccessTestCase.
*
*/
public AbstractReadOnlyAccessTestCase(String name) {
super(name);
}
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
@Override
public void testPutFromLoad() throws Exception {
putFromLoadTest(false);
}
@Override
public void testPutFromLoadMinimal() throws Exception {
putFromLoadTest(true);
}
private void putFromLoadTest(boolean minimal) throws Exception {
final String KEY = KEY_BASE + testCount++;
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
if (minimal)
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
else
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
sleep(250);
Object expected = isUsingInvalidation() ? null : VALUE1;
assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
BatchModeTransactionManager.getInstance().commit();
assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
@Override
public void testUpdate() throws Exception {
final String KEY = KEY_BASE + testCount++;
try {
localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
fail("Call to update did not throw exception");
}
catch (UnsupportedOperationException good) {}
}
}

View File

@ -1,140 +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.test.cache.jbc.entity;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.AssertionFailedError;
import org.hibernate.cache.access.AccessType;
import org.jboss.cache.transaction.BatchModeTransactionManager;
/**
* Base class for tests of TRANSACTIONAL access.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractTransactionalAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
/**
* Create a new AbstractTransactionalAccessTestCase.
*
*/
public AbstractTransactionalAccessTestCase(String name) {
super(name);
}
@Override
protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
}
public void testContestedPutFromLoad() throws Exception {
final String KEY = KEY_BASE + testCount++;
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
final CountDownLatch pferLatch = new CountDownLatch(1);
final CountDownLatch pferCompletionLatch = new CountDownLatch(1);
final CountDownLatch commitLatch = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(1);
Thread blocker = new Thread("Blocker") {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
pferLatch.countDown();
commitLatch.await();
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
completionLatch.countDown();
}
}
};
Thread putter = new Thread("Putter") {
public void run() {
try {
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
BatchModeTransactionManager.getInstance().commit();
}
catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
rollback();
}
catch (AssertionFailedError e) {
node1Failure = e;
rollback();
}
finally {
pferCompletionLatch.countDown();
}
}
};
blocker.start();
assertTrue("Active tx has done an update", pferLatch.await(1, TimeUnit.SECONDS));
putter.start();
assertTrue("putFromLoadreturns promtly", pferCompletionLatch.await(10, TimeUnit.MILLISECONDS));
commitLatch.countDown();
assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
assertThreadsRanCleanly();
long txTimestamp = System.currentTimeMillis();
assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
}
}

View File

@ -1,116 +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.test.cache.jbc.entity;
import java.util.Properties;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.Region;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.jbc.BasicRegionAdapter;
import org.hibernate.cache.jbc.CacheInstanceManager;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.entity.EntityRegionImpl;
import org.hibernate.test.cache.jbc.AbstractEntityCollectionRegionTestCase;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
/**
* Tests of EntityRegionImpl.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
/**
* Create a new EntityRegionImplTestCase.
*
* @param name
*/
public EntityRegionImplTestCase(String name) {
super(name);
}
@Override
protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
EntityRegion region = regionFactory.buildEntityRegion("test", properties, null);
assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
try
{
region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
fail("Did not get READ_ONLY");
}
catch (UnsupportedOperationException good) {}
try
{
region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
fail("Incorrectly got NONSTRICT_READ_WRITE");
}
catch (CacheException good) {}
try
{
region.buildAccessStrategy(AccessType.READ_WRITE);
fail("Incorrectly got READ_WRITE");
}
catch (CacheException good) {}
}
@Override
protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
return regionFactory.buildEntityRegion(regionName, properties, cdd);
}
@Override
protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
return mgr.getEntityCacheInstance();
}
@Override
protected Fqn getRegionFqn(String regionName, String regionPrefix) {
return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, EntityRegionImpl.TYPE);
}
@Override
protected void putInRegion(Region region, Object key, Object value) {
((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).insert(key, value, new Integer(1));
}
@Override
protected void removeFromRegion(Region region, Object key) {
((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).remove(key);
}
}

View File

@ -1,68 +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.test.cache.jbc.entity;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests TRANSACTIONAL access when MVCC locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public MvccInvalidatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(MvccInvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "mvcc-entity");
}
// Known failures
// Overrides
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
@Override
public boolean isBlockingReads() {
return false;
}
}

View File

@ -1,71 +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.test.cache.jbc.entity;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this
* version using pessimistic locking with READ_ONLY access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
private static EntityRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public MvccReadOnlyExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "mvcc-entity";
}
@Override
protected EntityRegionAccessStrategy getEntityAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,68 +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.test.cache.jbc.entity;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests READ_ONLY access when pessimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public MvccReadOnlyTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(MvccReadOnlyTestCase.class);
return getTestSetup(suite, "mvcc-entity");
}
// Known failures
// Overrides
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
@Override
public boolean isBlockingReads() {
return false;
}
}

View File

@ -1,62 +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.test.cache.jbc.entity;
import junit.framework.Test;
/**
* Tests TRANSACTIONAL access when pessimistic locking and replication are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public MvccReplicatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
return getTestSetup(MvccReplicatedTransactionalTestCase.class, "mvcc-shared");
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
@Override
public boolean isBlockingReads() {
return false;
}
}

View File

@ -1,71 +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.test.cache.jbc.entity;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this base
* version using Optimistic locking with TRANSACTIONAL access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class MvccTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
private static EntityRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public MvccTransactionalExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "mvcc-entity";
}
@Override
protected EntityRegionAccessStrategy getEntityAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,60 +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.test.cache.jbc.entity;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests TRANSACTIONAL access when optimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new OptimisticInvalidatedTransactionalTestCase.
*
* @param name
*/
public OptimisticInvalidatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(OptimisticInvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "optimistic-entity");
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,105 +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.test.cache.jbc.entity;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this
* version using Optimistic locking with READ_ONLY access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticReadOnlyExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
private static EntityRegionAccessStrategy localAccessStrategy;
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public OptimisticReadOnlyExtraAPITestCase(String name) {
super(name);
}
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
@Override
protected EntityRegionAccessStrategy getEntityAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
/**
* Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
*/
@Override
public void testLockItem() {
try {
getEntityAccessStrategy().lockItem(KEY, new Integer(1));
fail("Call to lockItem did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
/**
* Test method for {@link TransactionalAccess#lockRegion()}.
*/
@Override
public void testLockRegion() {
try {
getEntityAccessStrategy().lockRegion();
fail("Call to lockRegion did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
/**
* Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
*/
@Override
public void testAfterUpdate() {
try {
getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock());
fail("Call to afterUpdate did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
}

View File

@ -1,60 +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.test.cache.jbc.entity;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests READ_ONLY access when optimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public OptimisticReadOnlyTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(OptimisticReadOnlyTestCase.class);
return getTestSetup(suite, "optimistic-entity");
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,58 +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.test.cache.jbc.entity;
import junit.framework.Test;
/**
* Tests TRANSACTIONAL access when optimistic locking and replication are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public OptimisticReplicatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
return getTestSetup(OptimisticReplicatedTransactionalTestCase.class, "optimistic-shared");
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Invalidation", isUsingInvalidation());
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,172 +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.test.cache.jbc.entity;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.jbc.JBossCacheRegionFactory;
import org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory;
import org.hibernate.cache.jbc.builder.MultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc.entity.TransactionalAccess;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.cache.jbc.AbstractJBossCacheTestCase;
import org.hibernate.test.util.CacheTestUtil;
import org.jboss.cache.Cache;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this base
* version using Optimistic locking with TRANSACTIONAL access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class OptimisticTransactionalExtraAPITestCase extends AbstractJBossCacheTestCase {
public static final String REGION_NAME = "test/com.foo.test";
public static final String KEY = "KEY";
public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2";
private static EntityRegionAccessStrategy localAccessStrategy;
private static boolean optimistic;
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public OptimisticTransactionalExtraAPITestCase(String name) {
super(name);
}
protected void setUp() throws Exception {
super.setUp();
if (getEntityAccessStrategy() == null) {
Configuration cfg = createConfiguration();
JBossCacheRegionFactory rf = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
Cache localCache = rf.getCacheInstanceManager().getEntityCacheInstance();
optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
EntityRegion localEntityRegion = rf.buildEntityRegion(REGION_NAME, cfg.getProperties(), null);
setEntityRegionAccessStrategy(localEntityRegion.buildAccessStrategy(getAccessType()));
}
}
protected void tearDown() throws Exception {
super.tearDown();
}
protected Configuration createConfiguration() {
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
return cfg;
}
protected String getCacheConfigName() {
return "optimistic-entity";
}
protected boolean isUsingOptimisticLocking() {
return optimistic;
}
protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
}
protected EntityRegionAccessStrategy getEntityAccessStrategy() {
return localAccessStrategy;
}
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
/**
* This is just a setup test where we assert that the cache config is
* as we expected.
*/
public void testCacheConfiguration() {
assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
}
/**
* Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
*/
public void testLockItem() {
assertNull(getEntityAccessStrategy().lockItem(KEY, new Integer(1)));
}
/**
* Test method for {@link TransactionalAccess#lockRegion()}.
*/
public void testLockRegion() {
assertNull(getEntityAccessStrategy().lockRegion());
}
/**
* Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
*/
public void testUnlockItem() {
getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
/**
* Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
*/
public void testUnlockRegion() {
getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
/**
* Test method for {@link TransactionalAccess#afterInsert(java.lang.Object, java.lang.Object, java.lang.Object)}.
*/
public void testAfterInsert() {
assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterInsert(KEY, VALUE1, new Integer(1)));
}
/**
* Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
*/
public void testAfterUpdate() {
assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock()));
}
public static class MockSoftLock implements SoftLock {
}
}

View File

@ -1,64 +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.test.cache.jbc.entity;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests TRANSACTIONAL access when pessimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public PessimisticInvalidatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(PessimisticInvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "pessimistic-entity");
}
// Known failures
// Overrides
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,72 +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.test.cache.jbc.entity;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this
* version using pessimistic locking with READ_ONLY access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
private static EntityRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public PessimisticReadOnlyExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "pessimistic-entity";
}
@Override
protected EntityRegionAccessStrategy getEntityAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,65 +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.test.cache.jbc.entity;
import org.hibernate.test.util.CacheTestUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Tests READ_ONLY access when pessimistic locking and invalidation are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public PessimisticReadOnlyTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(PessimisticReadOnlyTestCase.class);
return getTestSetup(suite, "pessimistic-entity");
}
// Known failures
// Overrides
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,58 +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.test.cache.jbc.entity;
import junit.framework.Test;
/**
* Tests TRANSACTIONAL access when pessimistic locking and replication are used.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
/**
* Create a new PessimisticTransactionalAccessTestCase.
*
* @param name
*/
public PessimisticReplicatedTransactionalTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
return getTestSetup(PessimisticReplicatedTransactionalTestCase.class, "pessimistic-shared");
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Invalidation", isUsingInvalidation());
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
assertTrue("Synchronous mode", isSynchronous());
}
}

View File

@ -1,72 +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.test.cache.jbc.entity;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
/**
* Tests for the "extra API" in EntityRegionAccessStrategy; in this base
* version using Optimistic locking with TRANSACTIONAL access.
* <p>
* By "extra API" we mean those methods that are superfluous to the
* function of the JBC integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class PessimisticTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
private static EntityRegionAccessStrategy localAccessStrategy;
/**
* Create a new PessimisticAccessStrategyExtraAPITestCase.
*
* @param name
*/
public PessimisticTransactionalExtraAPITestCase(String name) {
super(name);
}
@Override
protected String getCacheConfigName() {
return "pessimistic-entity";
}
@Override
protected EntityRegionAccessStrategy getEntityAccessStrategy() {
return localAccessStrategy;
}
@Override
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
@Override
public void testCacheConfiguration() {
assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
}
}

View File

@ -1,126 +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.test.cache.jbc.functional;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cache.ReadWriteCache;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
/**
* Common requirement entity caching testing for each
* {@link org.hibernate.cache.RegionFactory} impl.
*
* @author Steve Ebersole
*/
public abstract class AbstractEntityCacheFunctionalTestCase extends CacheTestCaseBase {
// note that a lot of the functionality here is intended to be used
// in creating specific tests for each CacheProvider that would extend
// from a base test case (this) for common requirement testing...
public AbstractEntityCacheFunctionalTestCase(String x) {
super(x);
}
@Override
protected boolean getUseQueryCache() {
return false;
}
public void testEmptySecondLevelCacheEntry() throws Exception {
getSessions().evictEntity(Item.class.getName());
Statistics stats = getSessions().getStatistics();
stats.clear();
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(getPrefixedRegionName(Item.class.getName()));
Map cacheEntries = statistics.getEntries();
assertEquals(0, cacheEntries.size());
}
public void testStaleWritesLeaveCacheConsistent() {
Session s = openSession();
Transaction txn = s.beginTransaction();
VersionedItem item = new VersionedItem();
item.setName("steve");
item.setDescription("steve's item");
s.save(item);
txn.commit();
s.close();
Long initialVersion = item.getVersion();
// manually revert the version property
item.setVersion(new Long(item.getVersion().longValue() - 1));
try {
s = openSession();
txn = s.beginTransaction();
s.update(item);
txn.commit();
s.close();
fail("expected stale write to fail");
} catch (Throwable expected) {
// expected behavior here
if (txn != null) {
try {
txn.rollback();
} catch (Throwable ignore) {
}
}
} finally {
if (s != null && s.isOpen()) {
try {
s.close();
} catch (Throwable ignore) {
}
}
}
// check the version value in the cache...
SecondLevelCacheStatistics slcs = sfi().getStatistics().getSecondLevelCacheStatistics(
getPrefixedRegionName(VersionedItem.class.getName()));
Object entry = slcs.getEntries().get(item.getId());
Long cachedVersionValue;
if (entry instanceof ReadWriteCache.Lock) {
// FIXME don't know what to test here
cachedVersionValue = new Long(((ReadWriteCache.Lock) entry).getUnlockTimestamp());
} else {
cachedVersionValue = (Long) ((Map) entry).get("_version");
assertEquals(initialVersion.longValue(), cachedVersionValue.longValue());
}
// cleanup
s = openSession();
txn = s.beginTransaction();
item = (VersionedItem) s.load(VersionedItem.class, item.getId());
s.delete(item);
txn.commit();
s.close();
}
}

View File

@ -1,104 +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.test.cache.jbc.functional;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cache.ReadWriteCache;
import org.hibernate.stat.SecondLevelCacheStatistics;
/**
* A QueryCacheEnabledCacheProviderTestCase.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public abstract class AbstractQueryCacheFunctionalTestCase extends AbstractEntityCacheFunctionalTestCase {
/**
* Create a new QueryCacheEnabledCacheProviderTestCase.
*
* @param x
*/
public AbstractQueryCacheFunctionalTestCase(String x) {
super(x);
}
@Override
protected boolean getUseQueryCache() {
return true;
}
public void testQueryCacheInvalidation() {
Session s = openSession();
Transaction t = s.beginTransaction();
Item i = new Item();
i.setName("widget");
i.setDescription("A really top-quality, full-featured widget.");
s.persist(i);
t.commit();
s.close();
SecondLevelCacheStatistics slcs = s.getSessionFactory().getStatistics().getSecondLevelCacheStatistics(
getPrefixedRegionName(Item.class.getName()));
assertEquals(slcs.getPutCount(), 1);
assertEquals(slcs.getElementCountInMemory(), 1);
assertEquals(slcs.getEntries().size(), 1);
s = openSession();
t = s.beginTransaction();
i = (Item) s.get(Item.class, i.getId());
assertEquals(slcs.getHitCount(), 1);
assertEquals(slcs.getMissCount(), 0);
i.setDescription("A bog standard item");
t.commit();
s.close();
assertEquals(slcs.getPutCount(), 2);
Object entry = slcs.getEntries().get(i.getId());
Map map;
if (entry instanceof ReadWriteCache.Item) {
map = (Map) ((ReadWriteCache.Item) entry).getValue();
} else {
map = (Map) entry;
}
assertTrue(map.get("description").equals("A bog standard item"));
assertTrue(map.get("name").equals("widget"));
// cleanup
s = openSession();
t = s.beginTransaction();
s.delete(i);
t.commit();
s.close();
}
}

View File

@ -1,160 +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.test.cache.jbc.functional;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.Mappings;
import org.hibernate.dialect.Dialect;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.testing.tm.ConnectionProviderImpl;
import org.hibernate.testing.tm.TransactionManagerLookupImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides common configuration setups for cache testing.
*
* @author Brian Stansberry
*/
public abstract class CacheTestCaseBase extends FunctionalTestCase {
private static final Logger log = LoggerFactory.getLogger( CacheTestCaseBase.class );
private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
private String preferIPv4Stack;
// note that a lot of the functionality here is intended to be used
// in creating specific tests for each CacheProvider that would extend
// from a base test case (this) for common requirement testing...
public CacheTestCaseBase(String x) {
super(x);
}
public String[] getMappings() {
return new String[] {
"cache/jbc/functional/Item.hbm.xml",
"cache/jbc/functional/Customer.hbm.xml",
"cache/jbc/functional/Contact.hbm.xml"
};
}
public void configure(Configuration cfg) {
super.configure(cfg);
if (getRegionPrefix() != null) {
cfg.setProperty(Environment.CACHE_REGION_PREFIX, getRegionPrefix());
}
cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true");
cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(getUseQueryCache()));
cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, getTransactionManagerLookupClass().getName());
Class<?> transactionFactory = getTransactionFactoryClass();
if (transactionFactory != null)
cfg.setProperty( Environment.TRANSACTION_STRATEGY, transactionFactory.getName() );
configureCacheFactory(cfg);
}
protected String getRegionPrefix() {
return "test";
}
protected String getPrefixedRegionName(String regionName)
{
String prefix = getRegionPrefix() == null ? "" : getRegionPrefix() + ".";
return prefix + regionName;
}
public String getCacheConcurrencyStrategy() {
return "transactional";
}
/**
* Apply any region-factory specific configurations.
*
* @param cfg the Configuration to update.
*/
protected abstract void configureCacheFactory(Configuration cfg);
protected abstract Class<?> getCacheRegionFactory();
protected abstract boolean getUseQueryCache();
protected Class<?> getConnectionProviderClass() {
return ConnectionProviderImpl.class;
}
protected Class<?> getTransactionManagerLookupClass() {
return TransactionManagerLookupImpl.class;
}
protected Class<?> getTransactionFactoryClass() {
return null;
}
@Override
public void afterConfigurationBuilt(Mappings mappings, Dialect dialect) {
super.afterConfigurationBuilt(mappings, dialect);
// Try to ensure we use IPv4; otherwise cluster formation is very slow
preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
System.setProperty(PREFER_IPV4STACK, "true");
}
@Override
protected void cleanupTest() throws Exception {
try {
super.cleanupTest();
}
finally {
if (preferIPv4Stack == null)
System.clearProperty(PREFER_IPV4STACK);
else
System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
}
}
protected void sleep(long ms) {
try {
Thread.sleep(ms);
}
catch (InterruptedException e) {
log.warn("Interrupted during sleep", e);
}
}
}

View File

@ -1,48 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
~ 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
-->
<hibernate-mapping
package="org.hibernate.test.cache.jbc.functional">
<class name="Contact" table="Contacts">
<cache usage="transactional"/>
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<property name="tlf" not-null="true"/>
<many-to-one name="customer"
class="org.hibernate.test.cache.jbc.functional.Customer"
column="CUSTOMER_ID"/>
</class>
</hibernate-mapping>

Some files were not shown because too many files have changed in this diff Show More