HHH-5647 - Develop release process using Gradle
This commit is contained in:
parent
bea71a4562
commit
d2c88d55df
|
@ -1,6 +1,5 @@
|
|||
.gradle
|
||||
target
|
||||
build
|
||||
.idea
|
||||
.idea/*
|
||||
*.ipr
|
||||
|
|
40
build.gradle
40
build.gradle
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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)));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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>
|
||||
|
||||
|
|
@ -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());
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {}
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {}
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {}
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue